COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libcoopy_core/MergeOutputHumanDiff.cpp
Go to the documentation of this file.
00001 #include <coopy/MergeOutputHumanDiff.h>
00002 #include <coopy/SheetStyle.h>
00003 #include <coopy/DataSheet.h>
00004 
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 
00008 #define WANT_MAP2STRING
00009 #define WANT_VECTOR2STRING
00010 #include <coopy/Stringer.h>
00011 
00012 using namespace std;
00013 using namespace coopy::store;
00014 using namespace coopy::cmp;
00015 
00016 static string encoder(const string& x) {
00017   //SheetStyle style;
00018   //string result = DataSheet::encodeCell(x,style);
00019   //return (result!="")?result:"\"\"";
00020   string result = stringer_encoder(x);
00021   if (result.find("=")!=result.npos) {
00022     if (result[0]!='"') {
00023       // force quoting of any material containing the "=" symbol
00024       result = string("\"")+result+string("\"");
00025     }
00026   }
00027   return result;
00028 }
00029 
00030 static string encoder(const SheetCell& x) {
00031   return encoder(x.text);
00032 }
00033 
00034 static string cond(const vector<string>& names,
00035                    const map<string,SheetCell>& conds,
00036                    const map<string,SheetCell>& vals,
00037                    bool act) {
00038   string c = "";
00039   string pv = "";
00040   string v = "";
00041   bool nontrivial_past = false;
00042   for (vector<string>::const_iterator it = names.begin();
00043        it!=names.end();
00044        it++) {
00045     string name = *it;
00046     if (act) {
00047       //if (conds.find(name)!=conds.end()) {
00048         //fprintf(stderr,"Missing condition for %s\n", name.c_str());
00049         //exit(1);
00050       if (vals.find(name)!=vals.end()) {
00051         SheetCell pval;
00052         SheetCell val = vals.find(name)->second;
00053         if (conds.find(name)!=conds.end()) {
00054           pval = conds.find(name)->second;
00055           if (pval.text!="") {
00056             nontrivial_past = true;
00057           }
00058         }
00059         if (pv!="") pv += ",";
00060         pv += encoder(pval);
00061         if (v!="") v += ",";
00062         v += encoder(val);
00063         if (c!="") c += ",";
00064         c += encoder(name);
00065       }
00066         //}
00067     } else {
00068       if (conds.find(name)!=conds.end()) {
00069         if (vals.find(name)==vals.end()) {
00070           SheetCell val = conds.find(name)->second;
00071           if (c!="") c += ",";
00072           c += encoder(name);
00073           if (v!="") v += ",";
00074           v += encoder(val);
00075         }
00076       }
00077     }
00078   }
00079   if (act) {
00080     if (pv == "" || !nontrivial_past) {
00081       return c + " = " + v;
00082     }
00083     return c + " = " + pv + " -> " + v;
00084   }
00085   return c + " = " + v;
00086 }
00087 
00088 static string cond(const vector<string>& names,
00089                    const map<string,SheetCell>& vals,
00090                    string val_label, string cond_label) {
00091   SheetStyle style;
00092   string c = "";
00093   string v = "";
00094   size_t ct = 0;
00095   for (vector<string>::const_iterator it = names.begin();
00096        it!=names.end();
00097        it++) {
00098     string name = *it;
00099     if (vals.find(name)!=vals.end()) {
00100       ct++;
00101       SheetCell val = vals.find(name)->second;
00102       if (c!="") c += " ";
00103       c += encoder(name);
00104       if (v!="") v += " ";
00105       v += encoder(val);
00106     }
00107   }
00108   if (ct==names.size()) {
00109     c = "*";
00110     return string("  ") + val_label + " " + v;
00111   }
00112   return string("  ") + cond_label + " " + c + "\n  " + val_label + " " + v;
00113 }
00114 
00115 static string cond(const vector<string>& names) {
00116   string c = "";
00117   for (vector<string>::const_iterator it = names.begin();
00118        it!=names.end();
00119        it++) {
00120     string name = *it;
00121     if (c!="") c += " ";
00122     c += encoder(name);
00123   }
00124   return c;
00125 }
00126 
00127 MergeOutputHumanDiff::MergeOutputHumanDiff() {
00128 }
00129 
00130 bool MergeOutputHumanDiff::mergeStart() {
00131   fprintf(out,"dtbl: human-readable table difference format version 0.3\n\n");
00132   showed_initial_columns = false;
00133   return true;
00134 }
00135 
00136 bool MergeOutputHumanDiff::mergeDone() {
00137   checkMessage();
00138   return true;
00139 }
00140 
00141 bool MergeOutputHumanDiff::changeColumn(const OrderChange& change) {
00142   checkMessage();
00143   //printf("Got order change %s -> %s\n",
00144   //vector2string(change.namesBefore).c_str(),
00145   //vector2string(change.namesAfter).c_str());
00146   switch (change.mode) {
00147   case ORDER_CHANGE_DELETE:
00148     fprintf(out,"delete column: %s\n  before %s\n  after  %s\n\n", 
00149            change.namesBefore[change.subject].c_str(),
00150            vector2string(change.namesBefore).c_str(),
00151            vector2string(change.namesAfter).c_str());
00152     break;
00153   case ORDER_CHANGE_INSERT:
00154     fprintf(out,"insert column: %s\n  before %s\n  after  %s\n\n", 
00155            change.namesAfter[change.subject].c_str(),
00156            vector2string(change.namesBefore).c_str(),
00157            vector2string(change.namesAfter).c_str());
00158     break;
00159   case ORDER_CHANGE_MOVE:
00160     fprintf(out,"move column: %s\n  before %s\n  after  %s\n\n", 
00161            change.namesBefore[change.subject].c_str(),
00162            vector2string(change.namesBefore).c_str(),
00163            vector2string(change.namesAfter).c_str());
00164     break;
00165   default:
00166     fprintf(out,"  Unknown column operation\n\n");
00167     exit(1);
00168     break;
00169   }
00170   return true;
00171 }
00172 
00173 bool MergeOutputHumanDiff::changeRow(const RowChange& change) {
00174   checkMessage();
00175   //printf("Got row change %s ==> %s\n",
00176   // map2string(change.cond).c_str(),
00177   // map2string(change.val).c_str());
00178   switch (change.mode) {
00179   case ROW_CHANGE_INSERT:
00180     fprintf(out,"insert row:\n%s\n\n",
00181            cond(change.names,change.val,"add","where").c_str());
00182     break;
00183   case ROW_CHANGE_DELETE:
00184     fprintf(out,"delete row:\n%s\n\n",
00185            cond(change.names,change.cond,"remove","where").c_str());
00186     break;
00187   case ROW_CHANGE_UPDATE:
00188     fprintf(out,"update row:\n  where %s\n  set   %s\n\n",
00189            cond(change.names,change.cond,change.val,false).c_str(),
00190            cond(change.names,change.cond,change.val,true).c_str());
00191     break;
00192   default:
00193     fprintf(out,"  Unknown row operation\n\n");
00194     exit(1);
00195     break;
00196   }
00197   return true;
00198 }
00199 
00200 
00201 bool MergeOutputHumanDiff::declareNames(const std::vector<std::string>& names, 
00202                                           bool final) {
00203   string tag = "original ";
00204   string now = "";
00205   if (final) {
00206     tag = "";
00207     if (showed_initial_columns&&pending_message=="") {
00208       now = " now";
00209     }
00210   } else {
00211     showed_initial_columns = true;
00212   }
00213   string result = tag+"column names are"+now+": "+cond(names);
00214   pending_message = result;
00215   return true;
00216 }
00217 
00218 
00219 void MergeOutputHumanDiff::checkMessage() {
00220   if (pending_message!="") {
00221     fprintf(out,"%s\n\n", pending_message.c_str());
00222     pending_message = "";
00223   }
00224 }
00225 
00226 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines