Changeset 164
- Timestamp:
- 07/18/08 13:26:14 (6 months ago)
- Files:
-
- trunk/dba/dba/stream.cpp (modified) (2 diffs)
- trunk/dba/dba/stream.h (modified) (1 diff)
- trunk/dba/dba/xmlistream.cpp (modified) (6 diffs)
- trunk/dba/dba/xmlistream.h (modified) (2 diffs)
- trunk/dba/test/main.cpp (modified) (1 diff)
- trunk/dba/test/xmltestcase.cpp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dba/dba/stream.cpp
r160 r164 37 37 Stream::Stream() 38 38 : mRootTable(NULL), 39 mMemberList(new mt_mlist()) 39 mMemberList(new mt_mlist()), 40 mDebugFlag(false) 40 41 { 41 42 mIsOpen = false; … … 183 184 }; 184 185 186 const char* 187 Stream::getRootTableName(Storeable& pObj) { 188 //get name of root store table 189 const char* rootTableName = mRootTable; 190 if (rootTableName == NULL) { 191 const StoreTable* rootTable = getTable(pObj); 192 if (rootTable == NULL) 193 throw APIException("store table not defined, call get with overridden root table name"); 194 rootTableName = rootTable->getTableName(); 195 }; 196 if (rootTableName == NULL) 197 throw APIException("no store table for object"); 198 }; 185 199 186 200 void trunk/dba/dba/stream.h
r162 r164 173 173 */ 174 174 const StoreTable* getTable(Storeable& pObject); 175 /** 176 Get name of root table for object 177 @return root table name taken from mRootTable or topmost store table of passed object 178 */ 179 const char* getRootTableName(Storeable& pObj); 175 180 /** 176 181 Get root collection table for object trunk/dba/dba/xmlistream.cpp
r154 r164 13 13 #include "xmlutils.h" 14 14 #include "collectionfilter.h" 15 #include < iostream>15 #include <sstream> 16 16 17 17 namespace dba { … … 52 52 }; 53 53 54 ColMemberEntry* 55 XMLIStream::findNullMember(Storeable* pObject) { 56 return findMember(pObject, NULL); 57 }; 58 59 ColMemberEntry* 60 XMLIStream::findMember(Storeable* pObject, xmlNodePtr pNode) { 54 void 55 XMLIStream::updateCollection(Storeable* pParent, ColMemberEntry* pEntry, xmlNodePtr pNode) { 56 xmlNodePtr node = findNonTextNode(pNode); 57 if (node == NULL) 58 return; 59 60 CollectionFilterBase* childFilter = pEntry->getFilter(); 61 Storeable& child(childFilter->create()); 62 open(child,pEntry->getTableName()); 63 64 while(node != NULL) { 65 debug("checking node %s", (const char*)node->name); 66 if (!strcmp(getRootTableName(child),(const char*)node->name)) { 67 debug("updating data for member %s, starting at node %s", getRootTableName(child),(const char*)node->name); 68 childFilter->updateRef((char*)pParent + pEntry->getMemberOffset()); 69 Storeable* ref = childFilter->put(); 70 applyFilters(ref,node); 71 getChildren(ref,node->children); 72 }; 73 node = setNextNode(node); 74 }; 75 }; 76 77 void 78 XMLIStream::getChildren(Storeable* pObject, xmlNodePtr pNode) { 79 pNode = findNonTextNode(pNode); 61 80 const ColTable* table = getColTable(*pObject); 62 while(table != NULL) { 63 ColMemberEntry* entry = table->getMembers(); 64 while(entry != NULL) { 65 //FIXME conversion from file encoding? 66 if (pNode == NULL) { 67 if (entry->getFKeyName() == NULL) 68 return entry; 69 } else if (entry->getFKeyName() != NULL 70 && !strcmp(entry->getFKeyName(),(const char*)pNode->name)) 71 { 72 return entry; 81 while(pNode != NULL) { 82 debug("getChildren for %s at node %s", getRootTableName(*pObject), pNode->name); 83 //traverse through call collection members that 84 //have fkey name. 85 while(table != NULL) { 86 ColMemberEntry* entry = table->getMembers(); 87 while(entry != NULL) { 88 if (entry->getFKeyName() != NULL) { 89 //This means that that member entry 90 //describe list of elements that is a child of 91 //our node 92 xmlNodePtr node = findNode(pNode,entry->getFKeyName()); 93 if (node == NULL) { 94 std::ostringstream err; 95 err << "child node of '" << pNode->name << "' for member named '" << entry->getFKeyName() << "' not found"; 96 throw DataException(err.str()); 97 } else { 98 updateCollection(pObject,entry,node->children); 99 }; 100 } else { 101 updateCollection(pObject,entry,pNode); 102 }; 103 entry = entry->getNextMember(); 73 104 }; 74 entry = entry->getNextMember(); 75 }; 76 table = table->getNextTable(); 77 }; 78 return NULL; 79 }; 80 81 bool 82 XMLIStream::isClassMember(Storeable* pObject, xmlNodePtr pNode) { 83 //TODO check store table and find membe with the same name as pNode 84 return false; 85 }; 86 87 void 88 XMLIStream::getChildren(Storeable* pParent, xmlNodePtr pNode) { 89 pNode = findNonTextNode(pNode); 90 //if (pNode) std::cerr << "getChildren at node " << pNode->name << std::endl; 91 //ignore all nodes that are binded to pParent class members 92 while(pNode != NULL && !isClassMember(pParent, pNode)) { 93 ColMemberEntry* member = findMember(pParent, pNode); 94 //there is no collection member in table with the same fk_name 95 //as node name, but we still could have "default" collection member 96 //and in this case we should use it now 97 //default collection member has NULL fkey name 98 if (member == NULL ) { 99 member = findNullMember(pParent); 100 }; 101 102 if (member != NULL) { 103 //if member has fkey name then xmlNode points to 104 //it and objects that we want to add to this collection 105 //are one level below 106 if (member->getFKeyName() != NULL) 107 pNode = pNode->children; 108 109 CollectionFilterBase* childFilter = member->getFilter(); 110 Storeable& child(childFilter->create()); 111 open(child,member->getTableName()); 112 113 xmlNodePtr node = findNonTextNode(pNode); 114 while (node != NULL) { 115 mCurrentNode = findNonTextNode(node); 116 applyFilters(&child); 117 118 childFilter->updateRef((char*)pParent + member->getMemberOffset()); 119 Storeable* ref = childFilter->put(); 120 //recursive getChildren can be called only after put() 121 //- on pointer to already added object 122 if (node->children != NULL) 123 getChildren(ref,node->children); 124 node = setNextNode(node); 125 }; 126 127 //restore level to fkey node 128 if (member->getFKeyName() != NULL) 129 pNode = pNode->parent; 105 table = table->getNextTable(); 130 106 }; 131 107 pNode = setNextNode(pNode); … … 137 113 bool ret = false; 138 114 139 Storeable& parent(pFilter->create()); 140 //FIXME should find first node named pRootTable from current node 141 //FIXME open shuold find first node with id equal to parent.getId() (if set); 142 open(parent,pRootTable); 143 115 //create our root object using filter. 116 Storeable& rootobj(pFilter->create()); 117 118 open(rootobj,pRootTable); 119 120 //get name of root store table 121 const char* rootTableName = getRootTableName(rootobj); 122 123 debug("store table set to %s", rootTableName); 124 mCurrentNode = findNode(mCurrentNode, rootTableName); 125 while(mCurrentNode != NULL) { 144 126 145 while(mCurrentNode != NULL) { 146 147 //fill object data from attributes 148 applyFilters(&parent); 149 127 //apply non-collection filters to fetch data from 128 //attributes and subelements of node 129 applyFilters(&rootobj,mCurrentNode); 130 150 131 //traverse on xml child nodes and try to find members from 151 132 //collection tables 152 getChildren(&parent,mCurrentNode->children); 153 pFilter->put(); 133 Storeable* ref = pFilter->put(); 134 if (mCurrentNode->children != NULL) 135 getChildren(ref,mCurrentNode->children); 154 136 ret = true; 155 137 156 //if object has id then finish, else continue adding next objects to filter 157 if (!parent.isNew()) 158 break; 159 mCurrentNode = setNextNode(mCurrentNode); 138 //find node that corrsponds to root object store table 139 moveCurrentNode(rootTableName); 160 140 }; 161 141 return ret; 142 }; 143 144 xmlNsPtr 145 XMLIStream::getXMLNamespace(const char* pName, xmlNodePtr pNode) { 146 char* ns = XMLUtils::getNsFromName(pName); 147 xmlNsPtr nsptr = NULL; 148 if (ns != NULL) { 149 nsptr = xmlSearchNs(mDocument,pNode,(xmlChar*)ns); 150 if (nsptr == NULL) { 151 std::string err("Error loading data from node '"); 152 err += pName; 153 err += "'. Namespace not added, call addNamespace on XMLArchive first"; 154 delete [] ns; 155 throw APIException(err.c_str()); 156 }; 157 delete [] ns; 158 }; 159 return nsptr; 162 160 }; 163 161 164 162 xmlAttrPtr 165 163 XMLIStream::findAttribute(xmlNodePtr pNode, const char* pMemberName) { 166 char* ns = XMLUtils::getNsFromName(pMemberName);167 168 164 xmlAttrPtr ret = NULL; 169 if (ns != NULL) { 170 xmlNsPtr nsptr = xmlSearchNs(mDocument,pNode,(xmlChar*)ns); 171 if (nsptr == NULL) { 172 std::string err("Error loading data from node '"); 173 err += pMemberName; 174 err += "'. Namespace not added, call addNamespace on XMLArchive first"; 175 throw APIException(err.c_str()); 176 }; 165 xmlNsPtr nsptr = getXMLNamespace(pMemberName, pNode); 166 if (nsptr == NULL) { 167 ret = xmlHasProp(pNode,(xmlChar*)pMemberName); 168 } else { 177 169 char* name = XMLUtils::getNameWithoutNs(pMemberName); 178 170 ret = xmlHasNsProp(pNode,(xmlChar*)name,nsptr->href); 179 171 delete [] name; 172 }; 173 return ret; 174 }; 175 176 xmlNodePtr 177 XMLIStream::findNode(xmlNodePtr pNode, const char* pName) { 178 xmlNsPtr nsptr = getXMLNamespace(pName, pNode); 179 xmlChar* name = NULL; 180 if (nsptr == NULL) { 181 name = (xmlChar*)pName; 180 182 } else { 181 ret = xmlHasProp(pNode,(xmlChar*)pMemberName); 182 }; 183 delete [] ns; 184 return ret; 183 name = (xmlChar*)XMLUtils::getNameWithoutNs(pName); 184 }; 185 186 xmlNodePtr node = NULL; 187 for(node = pNode; node != NULL; node = node->next) { 188 if (!xmlNodeIsText(node) && !xmlStrcmp(name,node->name)) 189 break; 190 }; 191 192 if (nsptr != NULL) 193 delete [] name; 194 195 return node; 196 }; 197 198 void 199 XMLIStream::moveCurrentNode(const char* pName) { 200 mCurrentNode = mCurrentNode->next; 201 mCurrentNode = findNode(mCurrentNode, pName); 202 if (mCurrentNode == NULL) 203 return; 204 debug("mCurrentNode moved to %s", mCurrentNode->name != NULL ? (const char*)mCurrentNode->name : "(null)"); 185 205 }; 186 206 187 207 void 188 XMLIStream::applyFilters(Storeable* pObject ) {208 XMLIStream::applyFilters(Storeable* pObject, xmlNodePtr pNode) { 189 209 const StoreTable* tbl = Stream::getTable(*pObject); 190 210 const char* current_table_name = tbl->getTableName(); 191 211 if (current_table_name == NULL) 192 212 throw APIException("Root table has no name"); 213 debug("applying filters to tables with root name = '%s' from node '%s'",current_table_name,(const char*)pNode->name); 193 214 while(tbl != NULL) { 194 215 if (tbl->getTableName() != NULL) … … 198 219 dba::StoreableFilterBase* filter(member->getFilter()); 199 220 setFilterPtr(*filter,(char*)pObject + (int)(member->getMemberOffset() + tbl->getClassOffset())); 200 xmlAttrPtr attr = findAttribute( mCurrentNode,member->getMemberName());221 xmlAttrPtr attr = findAttribute(pNode,member->getMemberName()); 201 222 if (attr != NULL) { 202 223 xmlChar* xmldata = xmlNodeGetContent(attr->children); … … 221 242 if (mCurrentNode == NULL) 222 243 return false; 223 applyFilters(pObject );244 applyFilters(pObject,mCurrentNode); 224 245 mCurrentNode = setNextNode(mCurrentNode); 225 246 return true; … … 227 248 228 249 bool 229 XMLIStream::updateVars( ) {250 XMLIStream::updateVars(xmlNodePtr pNode) { 230 251 if (mCurrentNode == NULL) 231 252 return false; 232 253 for(VarMap::iterator it = mBindings.begin(); it != mBindings.end(); it++) { 233 if (!xmlStrcmp((xmlChar*)(it->mTable), mCurrentNode->name)) {254 if (!xmlStrcmp((xmlChar*)(it->mTable), pNode->name)) { 234 255 xmlAttrPtr attr = findAttribute(mCurrentNode, it->mField); 235 256 dba::StoreableFilterBase& filter(*(it->mFilter)); trunk/dba/dba/xmlistream.h
r155 r164 42 42 virtual void destroy(); 43 43 virtual bool getNext(Storeable* pObject); 44 virtual bool updateVars() ;44 virtual bool updateVars() { return updateVars(mCurrentNode); } 45 45 virtual bool isCollectionFilterSupported() const { return true; }; 46 46 virtual bool get(Storeable* pObject, const char* pRootTable = NULL) { return IStream::get(pObject, pRootTable); } … … 55 55 56 56 virtual void setIdsCondition(const char* pFKeyName, id pRelationId, const std::vector<id>& pIds); 57 void applyFilters(Storeable* pObject); 57 void applyFilters(Storeable* pObject, xmlNodePtr pNode); 58 bool updateVars(xmlNodePtr pNode); 58 59 xmlNodePtr setNextNode(xmlNodePtr pNode); 59 60 xmlNodePtr findNonTextNode(xmlNodePtr pNode); 60 ColMemberEntry* findMember(Storeable* pObject, xmlNodePtr pNode);61 ColMemberEntry* findNullMember(Storeable* pObject);62 bool isClassMember(Storeable* pObject, xmlNodePtr pNode);63 61 void getChildren(Storeable* pParent, xmlNodePtr pNode); 62 void updateCollection(Storeable* pParent, ColMemberEntry* pEntry, xmlNodePtr pNode); 64 63 xmlAttrPtr findAttribute(xmlNodePtr pNode, const char* pMemberName); 64 xmlNodePtr findNode(xmlNodePtr pNode, const char* pName); 65 void moveCurrentNode(const char* pName); 66 xmlNsPtr getXMLNamespace(const char* pName, xmlNodePtr pNode); 65 67 }; 66 68 trunk/dba/test/main.cpp
r157 r164 148 148 //runner.addTest(new CppUnit::TestCaller<PostgresSQLArchiveTestCase>("debug_test",&PostgresSQLArchiveTestCase::sqlError)); 149 149 //runner.addTest(new CppUnit::TestCaller<dba_tests::StringFilter>("debug_test",&dba_tests::StringFilter::test17)); 150 runner.addTest(new CppUnit::TestCaller<dba_tests::CSVTestCase>("debug_test",&dba_tests::CSVTestCase::invalidPos));150 //runner.addTest(new CppUnit::TestCaller<dba_tests::CSVTestCase>("debug_test",&dba_tests::CSVTestCase::invalidPos)); 151 151 //runner.addTest(new CppUnit::TestCaller<SQLite3SQLArchiveTestCase>("debug_test",&SQLite3SQLArchiveTestCase::transactions_rollback)); 152 //runner.addTest(dba_tests::XMLTestCase::suite());153 //runner.addTest(new CppUnit::TestCaller<dba_tests::XMLTestCase>("debug_test",&dba_tests::XMLTestCase:: load_two_inverted));152 runner.addTest(dba_tests::XMLTestCase::suite()); 153 //runner.addTest(new CppUnit::TestCaller<dba_tests::XMLTestCase>("debug_test",&dba_tests::XMLTestCase::sublist_two_store)); 154 154 //runner.addTest(new CppUnit::TestCaller<dba_tests::XMLTestCase>("debug_test",&dba_tests::XMLTestCase::store_two)); 155 155 //runner.addTest(new CppUnit::TestCaller<OdbcPluginTestCase>("debug_test",&OdbcPluginTestCase::dbConnection)); trunk/dba/test/xmltestcase.cpp
r159 r164 259 259 " <obj_with_list name=\"sub\">\n" 260 260 " <fk_owner>\n" 261 " <test_objects i_value=\"1\" f_value=\"1\" s_value=\"test_object\" d_value=\"2008-01-02Z00:00:00\"/>\n" 261 262 " <test_objects i_value=\"0\" f_value=\"0\" s_value=\"test_object\" d_value=\"2008-01-01Z00:00:00\"/>\n" 262 " <test_objects i_value=\"1\" f_value=\"1\" s_value=\"test_object\" d_value=\"2008-01-02Z00:00:00\"/>\n"263 263 " </fk_owner>\n" 264 264 " </obj_with_list>\n" … … 661 661 } 662 662 663 class SecondSingle : public TestObject { 664 DECLARE_STORE_TABLE() 665 public: 666 SecondSingle() {}; 667 SecondSingle(int pInt, double pDouble, const std::string& pStr, const tm& pDate) 668 : TestObject(pInt,pDouble,pStr,pDate) {}; 669 }; 670 671 BEGIN_STORE_TABLE(SecondSingle,TestObject,"secondsingle") 672 END_STORE_TABLE() 673 663 674 class TwoSingles : public dba::Storeable { 664 675 DECLARE_STORE_TABLE(); … … 668 679 : mName(pName), 669 680 mObj1(TestObject(1,1,"1",Utils::getDate(2008,1,1,0,0,0))), 670 mObj2( TestObject(20,20,"20",Utils::getDate(2008,2,2,0,0,0)))681 mObj2(SecondSingle(20,20,"20",Utils::getDate(2008,2,2,0,0,0))) 671 682 {}; 672 683 bool operator==(const TwoSingles& pObj) { … … 677 688 std::string mName; 678 689 TestObject mObj1; 679 TestObjectmObj2;690 SecondSingle mObj2; 680 691 }; 681 692 … … 693 704 " <twosingles parent=\"parent_name\">\n" 694 705 " <test_objects i_value=\"1\" f_value=\"1\" s_value=\"1\" d_value=\"2008-01-01Z00:00:00\"/>\n" 695 " < test_objectsi_value=\"20\" f_value=\"20\" s_value=\"20\" d_value=\"2008-02-02Z00:00:00\"/>\n"706 " <secondsingle i_value=\"20\" f_value=\"20\" s_value=\"20\" d_value=\"2008-02-02Z00:00:00\"/>\n" 696 707 " </twosingles>\n" 697 708 "</dba>\n" … … 708 719 TwoSingles loaded; 709 720 dba::XMLIStream stream(xmlArch.getIStream()); 721 //stream.enableDebug(); 710 722 stream.get(&loaded); 711 723 CPPUNIT_ASSERT(loaded == expected);
