/* Cfour (C++ Common Console Classes)
 * Copyright (C) 2001 Jeffrey Bakker
 *
 * 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.
 *
 *
 *  Author:              Jeffrey Bakker
 *  Filename:            cfconf.cpp
 *  File version:        1.0
 *
 *  ===========================================================================
 *
 *  Created on: Sept 2nd, 2001
 *
 *  ===========================================================================
 *
 *  Remark:
 *
 *  This is the implementation of the CFconf class. The methods in this class
 *  can convert data pairs in XML markup and back, and load & save XML data
 *  to & from a file. Adding and editing data to the loaded data pairs is also
 *  provided. Cfconf tries to interface with your programs which use XML data
 *  for its configuration files.
 *
 *  The data pairs are stored in a vector of datatype CFdatapair, and can then
 *  can be converted to XML markup stored in a vector of strings and written
 *  to a file. The opposite can also be done.
 *
 *  ===========================================================================
 *
 *  CFconf():
 *
 *   Description: default constructor.
 *
 *  ===========================================================================
 *
 *  CFconf(string filename, char io):
 *
 *   Description: Overloaded constructor that takes a filename and anI/O mode.
 *                This constructor calls rcIO.open(string,char).
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        filename
 *    - Type:        string
 *    - Description: the name of the file to open
 *
 *
 *    Parameter 2
 *    - Name:        io
 *    - Type:        char
 *    - Description: the mode in which to open the file ('i'/'o'). 
 *
 *  ===========================================================================
 *
 *  load():
 *
 *   Description: loads the currently open XML data file into memory.
 *
 *  ===========================================================================
 *
 *  save():
 *
 *   Description: saves the XML data currently in memory to the output file.
 *
 *  ===========================================================================
 *
 *  bool open_ifile(string file):
 *
 *   Description: This opens the specified file for reading and returns true,
 *                if the file exists. If not, it will return false. This
 *                method actually calls rcIO.openR(string).
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        file
 *    - Type:        string
 *    - Description: the name of the file to open
 *
 *   Output:
 *    - returns true if file opened correctly, false otherwise.
 *
 *  ===========================================================================
 *
 *  void set_doctype(string type):
 *
 *   Description: This set the document type with the string being passed.
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        type
 *    - Type:        string
 *    - Description: to be the name of the doctype
 *
 *  ===========================================================================
 *
 *  void XML_ize(CFdatapair pair):
 *
 *   Description: This converts a name/value pair and converts it into XML
 *                markup and places it in the XMLdata vector of strings.
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        pair
 *    - Type:        CFdatapair
 *    - Description: the pair of data to convert
 *
 *  ===========================================================================
 *
 *  void deXML_ize(string pair):
 *
 *   Description: This converts XML data into a name/value pair and places it
 *                in the Pairdata vector.
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        pair
 *    - Type:        string
 *    - Description: the XML string to convert
 *
 *  ===========================================================================
 *
 *  void to___XML():
 *
 *   Description: XMLize()'s the contents of the whole Datapair vector.
 *
 *  ===========================================================================
 *
 *  void from_XML():
 *
 *   Description: deXMLize()'s the contents of the whole XMLdata vector.
 *
 *  ===========================================================================
 *
 *  void read(CFdatapair inpair):
 *
 *   Description: Takes a datapairfrom outside the class (ie: your program),
 *                and adds it to the Pairdata vector.
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        inpair
 *    - Type:        CFdatapair
 *    - Description: the pair of data to add to the vector
 *
 *  ===========================================================================
 *
 *  void write_new():
 *
 *   Description: This will write a new XML-style config file.
 *
 *  ===========================================================================
 *
 *  void start():
 *
 *   Description: This will write the begin tags for a config file.
 *
 *  ===========================================================================
 *
 *  void end():
 *
 *   Description: This will write the end tags for a config file.
 *
 *  ===========================================================================
 *
 *  void printpairs():
 *
 *   Description: This will display the data in the Pairdata vector.
 *
 *  ===========================================================================
 *
 *  void add(string name, string value):
 *
 *   Description: Adds a name and value to the Pairdata vector.
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        name
 *    - Type:        string
 *    - Description: the name of the data to add
 *
 *
 *    Parameter 2
 *    - Name:        value
 *    - Type:        string
 *    - Description: the value of the data to add
 *
 *  ===========================================================================
 *
 *  void edit(string name, string value):
 *
 *   Description: Changes the value of the paid with the given name.
 *
 *   Input:
 *
 *    Parameter 1
 *    - Name:        name
 *    - Type:        string
 *    - Description: the name of the data pair to change
 *
 *
 *    Parameter 2
 *    - Name:        value
 *    - Type:        string
 *    - Description: the new value
 *
 *  ===========================================================================
 *
 * _______. ..
 */

#include "cfconf.h" 
#include <iostream> 
using namespace std;


// default constructor --------------------------------------------------
CFconf::CFconf() {}
// overloaded constructor -----------------------------------------------
CFconf::CFconf(string filename, char io) {rcIO.open(filename,io);}
//CFconf::~CFconf() {rcIO.close();}

// load XML data from file ----------------------------------------------
void CFconf::load() {

 string buffer;

 rcIO.rline(buffer);
 while (rcIO.ifile) {

  XMLdata.push_back(buffer);
  rcIO.rline(buffer);
 }
} //---------------------------------------------------------------------
// save XML data --------------------------------------------------------
void CFconf::save() {

 for(int i=0; i < XMLdata.size(); i++) {
  rcIO.write(XMLdata[i]);
  rcIO.write("\n");
 }
} //---------------------------------------------------------------------
// open files -----------------------------------------------------------
bool CFconf::open_ifile(string file) {return rcIO.openR(file);}
bool CFconf::open_ofile(string file) {return rcIO.openW(file);}

// set the document type ------------------------------------------------
void CFconf::set_doctype(string type) {doctype = type;}
//-----------------------------------------------------------------------
// convert a data pair into XML tag format ------------------------------
void CFconf::XML_ize(CFdatapair pair) {

 string xtmp;
// xtmp = s_tag(pair.getname()) + pair.getvalue() + tag_e(pair.getname());
 xtmp = "<" + pair.getname() + ">" + pair.getvalue() + "</" + pair.getname() + ">";

 XMLdata.push_back(xtmp);
} //---------------------------------------------------------------------
// convert XML <name>value</name> format into data pairs ----------------
void CFconf::deXML_ize(string pair) {

 string ntmp, vtmp;
 CFdatapair P;

 int open, close;
 
 open  = pair.find("<",0);
 close = pair.find(">",open);
 ntmp  = pair.substr(open+1,close-1);

 open = pair.find("</",close);
 vtmp = pair.substr(close+1,(open - close -1));

 P.setname(ntmp);
 P.setvalue(vtmp);
 Pairdata.push_back(P);
} //---------------------------------------------------------------------
// convert all data in the pairs vector to the XML vector ---------------
void CFconf::to___XML() {

 for(int i=0; i < Pairdata.size(); i++) {
  XML_ize(Pairdata[i]);
 }
} //---------------------------------------------------------------------
// convert all data in the XML vector to the pairs vector ---------------
void CFconf::from_XML() {

 for(int i=0; i < XMLdata.size(); i++) {
  deXML_ize(XMLdata[i]);
 }
} //---------------------------------------------------------------------

// reads the pair data from the progam (interfaces with your application)
void CFconf::read_new(CFdatapair inpair) {

 Pairdata.push_back(inpair);
} //---------------------------------------------------------------------
// creats a brand-new XML-style config file -----------------------------
void CFconf::write_new() {
 start();
 save();
 end();
} //---------------------------------------------------------------------
// creates the neccessay start tags -------------------------------------
void CFconf::start() {
 rcIO.write("<?xml version='1.0'?>\n");
 rcIO.write("<!DOCTYPE " + doctype + ">\n");
// rcIO.write(s_tag(doctype));
 rcIO.write("<" + doctype + ">\n");
}
// creates the neccessay end tags ---------------------------------------
void CFconf::end() {
// rcIO.write(tag_e(doctype));
 rcIO.write("</" + doctype + ">\n");
}

// the following methods return the string passed as a tag --------------
string s_tag(string tag) {return "<" + tag + ">";}     // start tag
string tag_e(string tag) {return "</" + tag + ">";}    // end tag
string _tag_(string tag) {return "<" + tag + "/>";}    // empty value tag
// ----------------------------------------------------------------------

void CFconf::printpairs() {

 for(int i=0; i < Pairdata.size(); i++) {
  cout << Pairdata[i].info() << endl;
 }
}

// add to the config list -----------------------------------------------
void CFconf::add(string name, string value) {

 CFdatapair tmp;
 tmp.setname(name);
 tmp.setvalue(value);
 Pairdata.push_back(tmp);
} //---------------------------------------------------------------------
// edit an existing value -----------------------------------------------
bool CFconf::edit(string name, string value) {

 bool found = false;
 int index = 0;
 int at = -1;

 while(!found || index < Pairdata.size()) {

  if(Pairdata[index].getname() == name) {found = true;}
  else index++;
 }
 if(found) {
  at = index;
  Pairdata[at].setvalue(value);
  return true;
 }

 return false;
} //---------------------------------------------------------------------