/////////////////////////////////////////////////////////////// // reqDB.cpp - Prototype for Project #1 // // ver 1.0 Requirements Database // // // // Language: Visual C++, ver 6.0 // // Platform: Del XPS1000, Windows 2000 Professional // // Application: CSE691, Pr1 demo, Fall 2000 // // Author: Jim Fawcett, CST 2-187, Syracuse Univ. // // (315) 443-3948, jfawcett@twcny.rr.com // /////////////////////////////////////////////////////////////// #pragma warning(disable : 4786) #include #include #include #include "reqDB.h" using namespace std; //----< convert string to integer >---------------------------- int itemNumber::makeInt(const char *str) { istringstream convert(str+1); int n=-1; convert >> n; if(n<0) return -1; return n; } //----< void constructor >------------------------------------- itemNumber::itemNumber() : _type('I'), _number(-1) { } //----< itemNumber constructor >------------------------------- itemNumber::itemNumber(const std::string &item) { switch(item[0]) { case 'A' : _type = 'A'; break; case 'B' : _type = 'B'; break; case 'D' : _type = 'D'; break; case 'P' : _type = 'P'; break; default : throw "unknown type encountered in itemNumber(...)"; } _number = makeInt(item.c_str()); } // //----< read state from string >------------------------------- void itemNumber::get(const string &s) { _type = s[0]; _number = makeInt(s.c_str()); } //----< make string representation of itemNumber >------------- string itemNumber::put() { string rep; rep += _type; ostringstream temp; temp << _number; rep += temp.str(); return rep; } //----< comparison operator for itemNumber >------------------- bool itemNumber::operator <(const itemNumber &in) const { if(_type------------------- bool itemNumber::operator==(const itemNumber &in) const { if(_type==in._type && _number==in._number) return true; return false; } //----< return type of item >---------------------------------- char itemNumber::type() const { return _type; } //----< return number of item >-------------------------------- int itemNumber::number() const { return _number; } // //----< is this a valid itemNumber? >-------------------------- bool itemNumber::isValid() { switch(_type) { case 'A' : case 'B' : case 'D' : if(_number > -1) return true; } return false; } //----< parse constructor >------------------------------------ parse::parse(const std::string &repStr) : rep(repStr) { } //----< validate string position >----------------------------- void parse::validate(int pos) { if(pos >= rep.size()) throw "unsuccessful search in parse"; } //----< find tag >--------------------------------------------- int parse::getTag(const std::string &tag) throw(char *) { int pos = rep.find(tag); validate(pos); if(rep[pos-1] != '<') throw "unsuccessful search in parse"; int posEnd = rep.find('>',pos); validate(posEnd); return pos+1; } // //----< get payload data from tagged item >-------------------- bool parse::getData(const std::string &tag, std::string &data) { try { int pos = getTag(tag); int posBeg = rep.find('>',pos) + 1; validate(posBeg); int posEnd = rep.find("------------------------- bool parse::getFirstAttr(const std::string &tag, std::string &attr) { try { int pos = getTag(tag); int posBeg = rep.find('\"',pos) + 1; validate(posBeg); int posEnd = rep.find('\"',posBeg+1); validate(posEnd); attr = rep.substr(posBeg,posEnd-posBeg); } catch(char *msg) { cout << "\n " << msg << "\n"; return false; } return true; } // //----< make begin tag >--------------------------------------- std::string begTag(const std::string &tag) { string temp; temp += '<'; temp += tag + '>'; return temp; } //----< make end tag >----------------------------------------- std::string endTag(const std::string &tag) { string temp; temp += "'; return temp; } //----< make closed tag >-------------------------------------- std::string closedTag(const std::string &tag) { string temp; temp += '<'; temp += tag + "/>"; return temp; } // //----< add attribute to a begin tag >------------------------- std::string addAttr(const std::string &begTag, const std::string &attr) { string temp = begTag; int pos1 = temp.find('>'); validate(pos1,temp); int pos2 = temp.find("/>"); int pos; if(pos2 < temp.size()) pos = pos2; else pos = pos1; temp.insert(pos,attr); temp.insert(pos," "); return temp; } //----< insert data after begin tag >-------------------------- std::string addData(const std::string &rep, const std::string &data) { string temp = rep; int pos = temp.find('>'); validate(pos,temp); temp.insert(pos+1,data); return temp; } //----< make tagged item >------------------------------------- std::string makeTaggedItem(const std::string &tag, const std::string &payload) { string temp; temp = begTag(tag); temp = addData(temp,payload); temp += endTag(tag); return temp; } // //----< extract number from rep string >----------------------- bool item::getNumber(const std::string &repStr) { parse itemParser(repStr); string itNum; if(itemParser.getFirstAttr("number",itNum)) { itemNum.get(itNum); return true; } return false; } //----< access item number >----------------------------------- itemNumber& item::number() { return itemNum; } //----< access item number >----------------------------------- itemNumber item::number() const { return itemNum; } //----< extract title from rep string >------------------------ bool item::getTitle(const std::string &repStr) { parse itemParser(repStr); string title; if(itemParser.getData("title",title)) { _title = title; return true; } return false; } //----< access item title >------------------------------------ std::string& item::title() { return _title; } //----< access item title >------------------------------------ std::string item::title() const { return _title; } // //----< extract text from rep string >------------------------- bool item::getText(const std::string &repStr) { parse itemParser(repStr); string text; if(itemParser.getData("text",text)) { _text = text; return true; } return false; } //----< access item text >------------------------------------- std::string& item::text() { return _text; } //----< access item text >------------------------------------- std::string item::text() const { return _text; } //----< extract allocations from rep string >------------------ bool item::getAlloc(const std::string &repStr) { parse itemParser(repStr); string allocs; if(itemParser.getData("allocate",allocs)) { istringstream temp(allocs); while(temp.good()) { string anAlloc; temp >> anAlloc; itemNumber itNum(anAlloc); alloc.insert(itNum); } return true; } return false; } //----< access item allocations >------------------------------ std::set& item::allocations() { return alloc; } //----< access const item allocations >------------------------ std::set item::allocations() const { return alloc; } // //----< convert itemNum to a string >-------------------------- std::string item::convert(const itemNumber &itNum) const { ostringstream temp; temp << itNum.type() << itNum.number(); return temp.str(); } //----< convert allocations to string >------------------------ std::string item::convert(const set& allocs) const { set::const_iterator it = allocs.begin(); string temp = convert(*(allocs.begin())); while(++it != allocs.end()) temp += string(" ") + convert(*it); return temp; } //----< extract priority from rep string >--------------------- bool item::getPriority(const std::string &repStr) { parse itemParser(repStr); string prior; if(itemParser.getData("priority",prior)) { if(prior=="normal") { pri = normal; return true; } else if(prior=="high") { pri = high; return true; } else if(prior=="low") { pri = low; return true; } else return false; } return false; } // //----< access item priority >--------------------------------- item::Priority& item::priority() { return pri; } //----< access const item priority >--------------------------- item::Priority item::priority() const { return pri; } //----< convert priority to string >--------------------------- std::string item::convert(const Priority &pri) const { string temp; switch(pri) { case high : temp = "high"; break; case normal : temp = "normal"; break; case low : temp = "low"; break; default : temp = "invalid"; } return temp; } // //----< convert string to item >------------------------------- bool item::getItem(const std::string &repStr) { if(!getNumber(repStr)) return false; if(!getTitle(repStr)) return false; if(!getText(repStr)) return false; if(!getAlloc(repStr)) return false; if(!getPriority(repStr)) return false; /* not implemented yet if(!getDate(repStr)) return false; */ return true; } //----< convert item to representation string >---------------- std::string item::putItem(bool format) const { string repStr = begTag("DBitem"); if(format) repStr += "\n "; string numStr = closedTag("number"); string attStr = "n=\""; attStr += convert(number()) + "\""; numStr = addAttr(numStr,attStr); repStr += numStr; if(format) repStr += "\n "; string ttlStr = makeTaggedItem("title",_title); repStr += ttlStr; if(format) repStr += "\n "; string txtStr = makeTaggedItem("text",_text); repStr += txtStr; if(format) repStr += "\n "; string allocs = convert(alloc); string allStr = makeTaggedItem("allocate",allocs); repStr += allStr; if(format) repStr += "\n "; string pris = convert(pri); string priStr = makeTaggedItem("priority",pris); repStr += priStr; if(format) repStr += "\n "; string datStr = makeTaggedItem("data","9-18-2000"); repStr += datStr; if(format) repStr += "\n"; repStr += ""; return repStr; } // //----< convert item to display string >----------------------- std::string item::showItem() const { ostringstream out; out << "\n ---------------------------------"; out << "\n item number = " << number().type() << number().number(); out << "\n item title = " << title(); out << "\n item text:"; istringstream in(text()); while(in.good()) { string line; getline(in,line); out << "\n " << line; } out << "\n allocations: " << convert(allocations()); out << "\n priority: " << convert(priority()); return out.str(); } // //----< ReqDB constructor >------------------------------------ ReqDB::ReqDB(const std::string &dbName) : currentItem(0) { ifstream in(dbName.c_str()); if(!in.good()) throw dbName; name = dbName; char ch; while(in.good()) { string buffer; do { in.read(&ch,1); buffer += ch; if(ch == '>') { int pos = buffer.find(""); if(pos < buffer.size()) break; } } while(in.good()); if(in.good()) { item DBitem; DBitem.getItem(buffer); array.push_back(DBitem); } } in.close(); } //----< ReqDB destructor >------------------------------------- ReqDB::~ReqDB() { ofstream out(name.c_str()); vector::iterator it; for(it=array.begin(); it!=array.end(); it++) { string itemStr = (*it).putItem(); out << itemStr.c_str(); } out.close(); } // //----< show a single item >----------------------------------- void ReqDB::showItem() { cout << array[currentItem++].showItem(); } //----< show entire database >--------------------------------- void ReqDB::show() { int save = currentItem; currentItem = 0; while(currentItem < size()) showItem(); currentItem = save; } //----< move to next item in db >------------------------------ bool ReqDB::next() { if(currentItem < size()-1) { ++currentItem; return true; } return false; } //----< move to previous item in db >-------------------------- bool ReqDB::prev() { if(currentItem > 0) { --currentItem; return true; } return false; } //----< reset current position in db >------------------------- void ReqDB::reset() { currentItem = 0; } ///////////////////////////////////////////////////////////////////////////// // NOTE: - no filtering or sorting operations are implemented yet // #ifdef TEST_REQDB ///////////////////////////////////////////////////////////////////////////// // testing itemNumber class // void testItemNumber() { cout << "\n Test itemNumber " << "\n================="; itemNumber first("A6"); if(first.isValid()) cout << "\n " << first << " is a valid itemNumber"; else cout << "\n " << first << " is not a valid itemNumber"; cout << "\n type = " << first.type(); cout << "\n number = " << first.number(); first.get("z15"); cout << "\n " << first.put(); if(first.isValid()) cout << " is a valid itemNumber"; else cout << " is not a valid itemNumber"; itemNumber array[] = { "A7", "A8", "A9", "A10" }; int i; for(i=0; i<4; i++) if(array[2] < array[i]) cout << "\n " << array[2] << " < " << array[i]; else cout << "\n " << array[2] << " >= " << array[i]; for(i=0; i<4; i++) if(array[2] == array[i]) cout << "\n " << array[2] << " = " << array[i]; else cout << "\n " << array[2] << " != " << array[i]; cout << endl; } // ///////////////////////////////////////////////////////////////////////////// // test parse class // void testParse() { cout << "\n Test parse " << "\n============"; string testStr = "payload string"; cout << "\n test string: " << testStr.c_str(); string temp; parse testParser(testStr); if(testParser.getFirstAttr("tag",temp)) cout << "\n attribute is: " << temp.c_str(); if(testParser.getData("tag",temp)) cout << "\n data is: " << temp.c_str() << endl; cout << "\n Test reverse parse " << "\n===================="; string rep = makeTaggedItem("tag","payload string"); cout << "\n making tagged item: " << rep; rep = addAttr(rep,"n=\"an attrib\""); cout << "\n adding attribute: " << rep; rep = addAttr(rep,"p=\"another\""); cout << "\n adding attribute: " << rep; rep = closedTag("tag"); rep = addAttr(rep,"n=\"an attribute\""); cout << "\n closed tag with attribute: " << rep; cout << endl; } // ///////////////////////////////////////////////////////////////////////////// // testing item class // void testItem() { cout << "\n Test item " << "\n==========="; string testStr; string testStr0 = ""; string testStr1 = ""; string testStr2 = "a title"; string testStr3 = "requirements text first line\nsecond line"; string testStr4 = "B6 B14"; string testStr5 = "high"; string testStr6 = "9-18-2000"; string testStr7 = ""; cout << "\n test string:" << "\n " << testStr0 << "\n " << testStr1 << "\n " << testStr2 << "\n " << testStr3 << "\n " << testStr4 << "\n " << testStr5 << "\n " << testStr6 << "\n " << testStr7 << endl; testStr += testStr0 + testStr1 + testStr2 + testStr3; testStr += testStr4 + testStr5 + testStr6 + testStr7; item test; test.getItem(testStr); cout << test.showItem() << "\n\n"; cout << test.putItem(true) << "\n\n"; cout << test.putItem() << "\n\n"; } // ///////////////////////////////////////////////////////////////////////////// // testing ReqDB class // void testDB() { cout << "\n Test requirements database " << "\n============================"; ReqDB db("db.txt"); db.show(); } //----< test stub >-------------------------------------------- int main() { cout << "\n Testing ReqDB Prototype " << "\n =========================\n"; // first page testItemNumber(); testParse(); cout << '\f'; // second page testItem(); cout << '\f'; // third page testDB(); cout << "\n\n"; return 0; } #endif