COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libcoopy_core/MergeOutputFilter.cpp
Go to the documentation of this file.
00001 #include <coopy/MergeOutputFilter.h>
00002 
00003 using namespace std;
00004 
00005 using namespace coopy::cmp;
00006 using namespace coopy::store;
00007 
00008 bool MergeOutputFilter::mergeAllDone() {
00009   Pool *pool = getFlags().pool;
00010   if (pool) {
00011     // default assumption is that IDs from parent are shared with remote
00012     // if assumption is not true, don't do the following.
00013 
00014     map<string,int> seen;
00015     for (std::list<RowUnit>::iterator it=rows.begin(); it!=rows.end(); it++) {
00016       RowUnit& unit = *it;
00017       RowChange& change = unit.change;
00018       if (change.mode == ROW_CHANGE_INSERT) {
00019         const std::string& name = unit.sheet_name;
00020 
00021         if (seen.find(name)==seen.end()) {
00022           PolySheet sheet;
00023           TextBook *book = getBook();
00024           if (!book) {
00025             fprintf(stderr,"Cannot find input\n");
00026           } else {
00027             sheet = getBook()->readSheet(name);
00028             if (sheet.isValid()) {
00029               addPoolsFromFlags(sheet,false);
00030               NameSniffer sniffer(sheet,getFlags());
00031               addPoolsFromSchema(sheet,sniffer,name,false);
00032             }
00033             seen[name] = 1;
00034           }
00035         }
00036 
00037         for (RowChange::txt2cell::const_iterator it = change.val.begin();
00038              it!=change.val.end(); it++) {
00039           PoolColumnLink link = pool->lookup(name,it->first);
00040           if (link.isInventor()) {
00041             PoolRecord& rec = link.getColumn().put(it->second,SheetCell());
00042             rec.linked = false;
00043           }
00044         }
00045       }
00046     }
00047     pool->setScanned();
00048   }
00049 
00050   if (desired_sheets.size()<2) {
00051     for (std::list<RowUnit>::iterator it=rows.begin(); it!=rows.end(); it++) {
00052       emitRow(*it);
00053     }
00054     for (std::map<std::string,SheetUnit>::iterator it=sheet_units.begin();
00055          it!=sheet_units.end(); it++) {
00056       emitPreambleIfNeeded(it->second);
00057     }
00058   } else {
00059     const CompareFlags& flags = getFlags();
00060     // could do with some optimization...
00061     for (int i=0; i<(int)flags.ordered_tables.size(); i++) {
00062       string name = flags.ordered_tables[i];
00063       for (std::list<RowUnit>::iterator it=rows.begin(); it!=rows.end(); it++) {
00064         if (it->sheet_name == name) {
00065           emitRow(*it);
00066         }
00067       }
00068       emitPreambleIfNeeded(sheet_units[name]);
00069     }
00070   }
00071   chain->mergeDone();
00072 
00073   return chain->mergeAllDone();
00074 }
00075 
00076 
00077 bool MergeOutputFilter::emitRow(const RowUnit& row) {
00078   string name = row.sheet_name;
00079   if (name!=last_sheet_name) {
00080     emitPreamble(sheet_units[name]);
00081   }
00082   string resolve = getFlags().resolve;
00083   if (resolve!="") {
00084     if (row.change.conflicted) {
00085       if (resolve=="ours") {
00086         return true;
00087       }
00088       RowChange change2 = row.change;
00089       if (resolve=="theirs") {
00090         for (RowChange::txt2cell::iterator it = change2.conflictingVal.begin(); 
00091              it != change2.conflictingVal.end(); it++) {
00092           change2.val[it->first] = it->second;
00093         }
00094       } else if (resolve=="neither") {
00095         for (RowChange::txt2cell::iterator it = 
00096                change2.conflictingParentVal.begin(); 
00097              it != change2.conflictingParentVal.end(); it++) {
00098           change2.val[it->first] = it->second;
00099         }
00100       }
00101       change2.conflictingVal.clear();
00102       change2.conflictingParentVal.clear();
00103       change2.conflicted = false;
00104       return chain->changeRow(change2);
00105     }
00106   }
00107   return chain->changeRow(row.change);
00108 }
00109 
00110 bool MergeOutputFilter::emitPreamble(const SheetUnit& preamble) {
00111   string name = preamble.sheet_name;
00112   //printf("emit [%s]?\n", name.c_str());
00113   if (name==last_sheet_name) { return false; }
00114   //printf("emit [%s]!\n", name.c_str());
00115 
00116   TextBook *book = getBook();
00117   if (getFlags().create_unknown_sheets && book) {
00118     PolySheet sheet;
00119     sheet = book->readSheet(name);
00120     if (sheet.isValid()) {
00121       if (getFlags().clean_sheets) {
00122         sheet.deleteData();
00123       }
00124     } else {
00125       dbg_printf("I need to create %s\n", name.c_str());
00126 
00127       for (std::list<PoolChange>::const_iterator it=preamble.pools.begin();
00128            it != preamble.pools.end(); it++) {
00129         dbg_printf("apply pool\n");
00130         applyPool(*it);
00131       }
00132 
00133       vector<string> names;
00134       if (preamble.have_name1) {
00135         names = preamble.name1.names;
00136       } else if (preamble.have_name0) {
00137         names = preamble.name1.names;
00138       }
00139 
00140       if (names.size()==0) {
00141         fprintf(stderr,"Do not know column names to create %s\n", name.c_str());
00142         exit(1);
00143       }
00144       SimpleSheetSchema sss0, sss1;
00145       sss0.setSheetName(name.c_str());
00146       for (int i=0; i<(int)names.size(); i++) {
00147         sss0.addColumn(names[i].c_str());
00148       }
00149       book->setPool(getFlags().pool);
00150       book->fixSchema(sss0,sss1);
00151       book->addSheet(sss1);
00152     }
00153   }
00154 
00155   if (name!="") {
00156     chain->setSheet(name.c_str());
00157   }
00158   last_sheet_name = name;
00159   if (started_sheets.find(name)!=started_sheets.end()) {
00160     return true;
00161   }
00162   started_sheets[name] = 1;
00163 
00164   if (preamble.have_name0) {
00165     chain->changeName(preamble.name0);
00166   }
00167   for (std::list<OrderChange>::const_iterator it = preamble.orders.begin();
00168        it != preamble.orders.end(); it++) {
00169     chain->changeColumn(*it);
00170   }
00171   if (preamble.have_name1) {
00172     chain->changeName(preamble.name1);
00173   }
00174   for (std::list<PoolChange>::const_iterator it = preamble.pools.begin();
00175        it != preamble.pools.end(); it++) {
00176     chain->changePool(*it);
00177   }
00178   return true;
00179 }
00180 
00181 
00182 bool MergeOutputFilter::mergeStart() {
00183   const CompareFlags& flags = getFlags();
00184   for (int i=0; i<(int)flags.ordered_tables.size(); i++) {
00185     desired_sheets[flags.ordered_tables[i]] = 1;
00186   }
00187   return chain->mergeStart();
00188 }
00189 
00190 
00191 bool MergeOutputFilter::emitPreambleIfNeeded(const SheetUnit& preamble) { 
00192   if (preamble.row_count==0) {
00193     if (getFlags().canSchema()||preamble.orders.size()>0||
00194         preamble.pools.size()>0) {
00195       return emitPreamble(preamble);
00196     }
00197   }
00198   return true;
00199 }
00200 
00201 
00202 bool MergeOutputFilter::changeRow(const RowChange& change) { 
00203   if (!isActiveTable()) return false;
00204   SheetUnit unit = getSheetUnit();
00205   if (!(unit.have_name0||unit.have_name1)) {
00206     NameChange nc;
00207     nc.mode = NAME_CHANGE_DECLARE;
00208     nc.constant = true;
00209     nc.final = true;
00210     nc.names = change.allNames;
00211     changeName(nc);
00212   }
00213   switch (change.mode) {
00214   case ROW_CHANGE_INSERT:
00215     if (!getFlags().canInsert()) { return false; }
00216     break;
00217   case ROW_CHANGE_DELETE:
00218     if (!getFlags().canDelete()) { return false; }
00219     break;
00220   case ROW_CHANGE_UPDATE:
00221   case ROW_CHANGE_MOVE:
00222     if (!getFlags().canUpdate()) { return false; }
00223     break;
00224   }
00225   rows.push_back(RowUnit(sheet_name,change));
00226   getSheetUnit().row_count++;
00227   return true;
00228 }
00229 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines