COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libcoopy_core/MergeOutputCsvDiff.cpp
Go to the documentation of this file.
00001 
00002 
00003 /*
00004   Changes in 0.4:
00005   Version number change.
00006   The special "*" character goes away.
00007   A "row transform" operation is added.
00008   Context distinguished from index
00009 
00010   Changes in 0.5:
00011   sheet command
00012   
00013  */
00014 
00015 #include <coopy/MergeOutputCsvDiff.h>
00016 #include <coopy/SheetStyle.h>
00017 #include <coopy/DataSheet.h>
00018 
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 
00022 #define WANT_MAP2STRING
00023 #define WANT_VECTOR2STRING
00024 #include <coopy/Stringer.h>
00025 
00026 using namespace std;
00027 using namespace coopy::store;
00028 using namespace coopy::cmp;
00029 
00030 #define OP_MATCH "*"
00031 #define OP_ASSIGN "="
00032 #define OP_MATCH_ASSIGN "*="
00033 #define OP_CONTEXT "#"
00034 #define OP_NONE ""
00035 
00036 MergeOutputCsvDiff::MergeOutputCsvDiff() {
00037 }
00038 
00039 bool MergeOutputCsvDiff::mergeStart() {
00040 
00041   currentSheetName = "";
00042   pendingSheetName = "";
00043   result.setStrict(0);
00044   mergeClear();
00045   result.addField("dtbl",false);
00046   result.addField("csv",false);
00047   result.addField("version",false);
00048   result.addField("0.5",false);
00049   result.addRecord();
00050 
00051   return true;
00052 }
00053 
00054 bool MergeOutputCsvDiff::mergeClear() {
00055   ops.clear();
00056   nops.clear();
00057   activeColumn.clear();
00058   showForSelect.clear();
00059   showForDescribe.clear();
00060   prevSelect.clear();
00061   prevDescribe.clear();
00062   constantColumns = true;
00063   columns.clear();
00064   showedColumns = false;
00065   return true;
00066 }
00067 
00068 
00069 bool MergeOutputCsvDiff::mergeDone() {
00070   mergeClear();
00071   return true;
00072 }
00073 
00074 bool MergeOutputCsvDiff::mergeAllDone() {
00075   SheetStyle style;
00076   //SheetCell c = result.cellSummary(0,0);
00077   fprintf(out,"%s",result.encode(style).c_str());
00078   return true;
00079 }
00080 
00081 
00082 bool MergeOutputCsvDiff::changeColumn(const OrderChange& change) {
00083   constantColumns = false;
00084   switch (change.mode) {
00085   case ORDER_CHANGE_DELETE:
00086     clearThroat();
00087     result.addField("column",false);
00088     result.addField("delete",false);
00089     //result.addField(ROW_COL,false);
00090     for (int i=0; i<(int)change.namesAfter.size(); i++) {
00091       result.addField(change.namesAfter[i].c_str(),false);
00092     }
00093     result.addRecord();
00094     break;
00095   case ORDER_CHANGE_INSERT:
00096     clearThroat();
00097     result.addField("column",false);
00098     result.addField("insert",false);
00099     //result.addField(ROW_COL,false);
00100     for (int i=0; i<(int)change.namesAfter.size(); i++) {
00101       result.addField(change.namesAfter[i].c_str(),false);
00102     }
00103     result.addRecord();
00104     break;
00105   case ORDER_CHANGE_MOVE:
00106     clearThroat();
00107     result.addField("column",false);
00108     result.addField("move",false);
00109     //result.addField(ROW_COL,false);
00110     for (int i=0; i<(int)change.namesAfter.size(); i++) {
00111       result.addField(change.namesAfter[i].c_str(),false);
00112     }
00113     result.addRecord();
00114     break;
00115   case ORDER_CHANGE_RENAME:
00116     clearThroat();
00117     result.addField("column",false);
00118     result.addField("rename",false);
00119     for (int i=0; i<(int)change.namesAfter.size(); i++) {
00120       result.addField(change.namesAfter[i].c_str(),false);
00121     }
00122     result.addRecord();
00123     break;
00124   default:
00125     fprintf(stderr,"  Unknown column operation\n\n");
00126     exit(1);
00127     break;
00128   }
00129   activeColumn.clear();
00130   for (int i=0; i<(int)change.namesAfter.size(); i++) {
00131     activeColumn[change.namesAfter[i]] = true;
00132   }
00133   nops = change.namesAfter;
00134   return true;
00135 }
00136 
00137 bool MergeOutputCsvDiff::operateRow(const RowChange& change, const char *tag) {
00138   vector<string> lnops;
00139   for (int i=0; i<(int)change.names.size(); i++) {
00140     if (activeColumn[change.names[i]]) {
00141       lnops.push_back(change.names[i]);
00142     }
00143   }
00144   if (lnops!=nops) {
00145     if (!showedColumns) {
00146       clearThroat();
00147       result.addField("column",false);
00148       result.addField("name",false);
00149       for (int i=0; i<(int)columns.size(); i++) {
00150         result.addField(columns[i].c_str(),false);
00151       }
00152       result.addRecord();
00153       showedColumns = true;
00154     }
00155     if (columns!=lnops) {
00156       clearThroat();
00157       result.addField("link",false);
00158       result.addField("name",false);
00159       for (int i=0; i<(int)change.names.size(); i++) {
00160         if (activeColumn[change.names[i]]) {
00161           result.addField(change.names[i].c_str(),false);
00162         }
00163       }
00164       result.addRecord();
00165       columns = lnops;
00166     }
00167     nops = lnops;
00168   }
00169 
00170   if (prevSelect!=showForSelect || prevDescribe!=showForDescribe) {
00171     clearThroat();
00172     result.addField((string(tag)=="act")?"link":"row",false);
00173     result.addField(tag,false);
00174     for (int i=0; i<(int)change.names.size(); i++) {
00175       if (activeColumn[change.names[i]]) {
00176         result.addField(ops[i].c_str(),false);
00177       }
00178     }
00179     result.addRecord();
00180   }
00181   return true;
00182 }
00183 
00184 bool MergeOutputCsvDiff::updateRow(const RowChange& change, const char *tag,
00185                                    bool select, bool update, bool practice) {
00186   bool ok = true;
00187 
00188   if (!practice) {
00189     clearThroat();
00190     result.addField("row",false);
00191     result.addField(tag,false);
00192   }
00193   for (int i=0; i<(int)change.names.size(); i++) {
00194     string name = change.names[i];
00195     if (activeColumn[name]) {
00196       bool shown = false;
00197       if (change.cond.find(name)!=change.cond.end() && 
00198           showForSelect[name] && select) {
00199         if (!practice) {
00200           clearThroat();
00201           result.addField(change.cond.find(name)->second);
00202         }
00203         shown = true;
00204       }
00205       if (change.val.find(name)!=change.val.end() && 
00206           showForDescribe[name] && update) {
00207         if (!practice) {
00208           clearThroat();
00209           result.addField(change.val.find(name)->second);
00210         }
00211         if (shown) ok = false; // collision
00212         shown = true;
00213       }
00214       if (!shown) {
00215         if (!practice) {
00216           clearThroat();
00217           result.addField("",false);
00218         }
00219       }
00220     }
00221   }
00222   if (!practice) {
00223     result.addRecord();
00224   }
00225   return ok;
00226 }
00227 
00228 bool MergeOutputCsvDiff::changeRow(const RowChange& change) {
00229   vector<string> lops;
00230   activeColumn.clear();
00231   prevSelect = showForSelect;
00232   prevDescribe = showForDescribe;
00233   showForSelect.clear();
00234   showForDescribe.clear();
00235   for (int i=0; i<(int)change.names.size(); i++) {
00236     string name = change.names[i];
00237     bool condActive = false;
00238     bool valueActive = false;
00239     if (change.cond.find(name)!=change.cond.end()) {
00240       condActive = true;
00241     }
00242     if (change.val.find(name)!=change.val.end()) {
00243       valueActive = true;
00244     }
00245     bool shouldMatch = condActive && change.indexes.find(name)->second;
00246     bool shouldAssign = valueActive;
00247     if (shouldAssign) {
00248       // conservative choice, should be optional
00249       if (change.cond.find(name)!=change.cond.end()) {
00250         shouldMatch = true;
00251       }
00252     }
00253     //printf("==> %s %d %d %d %d\n", name.c_str(), condActive, valueActive,
00254     //shouldMatch, shouldAssign);
00255     //bool shouldShow = shouldMatch || shouldAssign;
00256 
00257     if (change.mode==ROW_CHANGE_INSERT) {
00258       // we do not care about matching
00259       shouldMatch = prevSelect[name];
00260       shouldAssign = true;
00261     }
00262     if (change.mode==ROW_CHANGE_DELETE) {
00263       // we do not care about assigning
00264       shouldAssign = prevDescribe[name];
00265       shouldMatch = true;
00266     }
00267 
00268     // ignoring shouldShow for now.
00269     int opidx = (shouldMatch?2:0) + (shouldAssign?1:0);
00270     string opi[4] = {
00271       OP_NONE,         // !match  !assign
00272       OP_ASSIGN,       // !match   assign
00273       OP_MATCH,        //  match  !assign
00274       OP_MATCH_ASSIGN, //  match   assign
00275     };
00276     string op = opi[opidx];
00277     
00278     if (opidx!=0) {
00279       activeColumn[name] = true;
00280     }
00281 
00282     // no way yet to communicate CONTEXT request
00283     lops.push_back(op);
00284     //showForSelect.push_back(shouldMatch);
00285     //showForDescribe.push_back(shouldAssign);
00286     showForSelect[name] = shouldMatch;
00287     showForDescribe[name] = shouldAssign;
00288   }
00289 
00290   if (lops!=ops) {
00291     ops = lops;
00292     operateRow(change,"act");
00293   }
00294   switch (change.mode) {
00295   case ROW_CHANGE_INSERT:
00296     updateRow(change,"insert",false,true,false);
00297     break;
00298   case ROW_CHANGE_DELETE:
00299     updateRow(change,"delete",true,false,false);
00300     break;
00301   case ROW_CHANGE_MOVE:
00302     {
00303       bool terse = updateRow(change,"practice",true,true,true);
00304       if (terse) {
00305         updateRow(change,"move",true,true,false);
00306       } else {
00307         updateRow(change,"select",true,false,false);
00308         updateRow(change,"move",false,true,false);
00309       }
00310     }
00311     break;
00312   case ROW_CHANGE_CONTEXT:
00313     updateRow(change,(change.cond.size()>0)?"after":"start",true,false,false);
00314     break;
00315   case ROW_CHANGE_UPDATE:
00316     {
00317       bool terse = updateRow(change,"practice",true,true,true);
00318       if (terse) {
00319         updateRow(change,"update",true,true,false);
00320       } else {
00321         updateRow(change,"select",true,false,false);
00322         updateRow(change,"update",false,true,false);
00323       }
00324     }
00325     break;
00326   default:
00327     fprintf(stderr,"  Unknown row operation\n\n");
00328     exit(1);
00329     break;
00330   }
00331   return true;
00332 }
00333 
00334 
00335 bool MergeOutputCsvDiff::changeName(const NameChange& change) {
00336   const vector<string>& names = change.names;
00337   bool final = change.final;
00338   bool constant = change.constant;
00339   if (!final) {
00340     activeColumn.clear();
00341     for (int i=0; i<(int)names.size(); i++) {
00342       activeColumn[names[i]] = true;
00343       showForSelect[names[i]] = true;
00344       showForDescribe[names[i]] = true;
00345     }
00346     if (!constant) {
00347       clearThroat();
00348       result.addField("column",false);
00349       result.addField("name",false);
00350       //result.addField(ROW_COL,false);
00351       for (int i=0; i<(int)names.size(); i++) {
00352         result.addField(names[i].c_str(),false);
00353       }
00354       result.addRecord();
00355       showedColumns = true;
00356     }
00357   }
00358   columns = names;
00359   return true;
00360 }
00361 
00362 bool MergeOutputCsvDiff::setSheet(const char *name) {
00363   pendingSheetName = name;
00364   return true;
00365 }
00366 
00367 bool MergeOutputCsvDiff::clearThroat() {
00368   if (currentSheetName!=pendingSheetName) {
00369     result.addField("table",false);
00370     result.addField("name",false);
00371     result.addField(pendingSheetName.c_str(),false);
00372     result.addRecord();
00373     currentSheetName = pendingSheetName;
00374   }
00375   return true;
00376 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines