Changeset 138
- Timestamp:
- 05/23/08 19:42:21 (8 months ago)
- Files:
-
- trunk/dba/dba/ostream.cpp (modified) (2 diffs)
- trunk/dba/dba/ostream.h (modified) (2 diffs)
- trunk/dba/dba/xmlistream.cpp (modified) (4 diffs)
- trunk/dba/dba/xmlistream.h (modified) (3 diffs)
- trunk/dba/dba/xmlostream.cpp (modified) (3 diffs)
- trunk/dba/dba/xmlostream.h (modified) (1 diff)
- trunk/dba/test/testobject.h (modified) (1 diff)
- trunk/dba/test/xmltestcase.cpp (modified) (3 diffs)
- trunk/dba/test/xmltestcase.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dba/dba/ostream.cpp
r136 r138 45 45 46 46 bool 47 OStream::put Child(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) {47 OStream::putMemberChildren(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 48 48 bool ret = false; 49 49 bool was_changed = false; … … 126 126 const char* obj_table = member->getTableName(); 127 127 //call archive specific store alghoritm 128 bool was_changed = putChild(pObject, *member, filter, obj_table); 128 initMemberChildrenStore(*pObject,*member); 129 bool was_changed = putMemberChildren(pObject, *member, filter, obj_table); 130 endMemberChildrenStore(*pObject,*member); 129 131 if (!ret) ret = was_changed; 130 132 //move forward in loop trunk/dba/dba/ostream.h
r136 r138 68 68 virtual ~OStream() {}; 69 69 protected: 70 virtual void initMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember) {}; 71 virtual void endMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember) {}; 70 72 /** 71 73 Default implementation for BIND_COL store that works on data stored in relations and … … 78 80 @return true if at least one subobject object was stored in archive, false otherwise 79 81 */ 80 virtual bool put Child(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName);82 virtual bool putMemberChildren(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName); 81 83 /** 82 84 Store all Storeable objects on sublists listed as BIND_COL in store table trunk/dba/dba/xmlistream.cpp
r133 r138 11 11 // 12 12 #include "xmlistream.h" 13 #include "collectionfilter.h" 14 #include <iostream> 13 15 14 16 namespace dba { … … 19 21 mParentNode(pNode) 20 22 { 21 mCurrentNode = mParentNode->children; 22 setNextNode(); 23 mCurrentNode = setNextNode(mParentNode->children); 23 24 } 24 25 25 void 26 XMLIStream::setNextNode() { 27 while( mCurrentNode && xmlIsBlankNode(mCurrentNode) == 1) 28 mCurrentNode = mCurrentNode->next; 26 xmlNodePtr 27 XMLIStream::setNextNode(xmlNodePtr pNode) { 28 do { 29 if (pNode) 30 pNode = pNode->next; 31 else 32 return NULL; 33 34 } while(xmlIsBlankNode(pNode) == 1); 35 return pNode; 29 36 }; 30 37 … … 39 46 }; 40 47 41 bool 42 XMLIStream::getNext(Storeable* pObject) { 43 if (mCurrentNode == NULL) 44 return false; 48 ColMemberEntry* 49 XMLIStream::findNullMember(Storeable* pObject) { 50 return findMember(pObject, NULL); 51 }; 52 53 ColMemberEntry* 54 XMLIStream::findMember(Storeable* pObject, xmlNodePtr pNode) { 55 const ColTable* table = getColTable(*pObject); 56 while(table != NULL) { 57 ColMemberEntry* entry = table->getMembers(); 58 while(entry != NULL) { 59 //FIXME conversion from file encoding? 60 if (pNode == NULL) { 61 if (entry->getFKeyName() == NULL) 62 return entry; 63 } else if (!strcmp(entry->getFKeyName(),(const char*)pNode->name)) { 64 return entry; 65 }; 66 entry = entry->getNextMember(); 67 }; 68 table = table->getNextTable(); 69 }; 70 return NULL; 71 }; 72 73 bool 74 XMLIStream::isClassMember(Storeable* pObject, xmlNodePtr pNode) { 75 //TODO check store table and find membe with the same name as pNode 76 return false; 77 }; 78 79 void 80 XMLIStream::getChildren(Storeable* pParent, xmlNodePtr pNode) { 81 pNode = setNextNode(pNode); 82 //if (pNode) std::cerr << "getChildren at node " << pNode->name << std::endl; 83 //ignore all nodes that are binded to pParent class members 84 while(pNode != NULL && !isClassMember(pParent, pNode)) { 85 ColMemberEntry* member = findMember(pParent, pNode); 86 //there is no collection member in table with the same fk_name 87 //as node name, but we still could have "default" collection member 88 //and in this case we should use it now 89 //default collection member has NULL fkey name 90 if (member == NULL ) { 91 member = findNullMember(pParent); 92 }; 93 94 if (member != NULL) { 95 //if member has fkey name then xmlNode points to 96 //it and objects that we want to add to this collection 97 //are one level below 98 if (member->getFKeyName() != NULL) 99 pNode = pNode->children; 100 101 CollectionFilterBase* childFilter = member->getFilter(); 102 Storeable& child(childFilter->create()); 103 open(child,member->getTableName()); 104 105 xmlNodePtr node = setNextNode(pNode); 106 while (node != NULL) { 107 mCurrentNode = node; 108 while(mCurrentNode && (xmlIsBlankNode(mCurrentNode) == 1)) 109 mCurrentNode = mCurrentNode->next; 110 applyFilters(&child); 111 if (node->children != NULL) 112 getChildren(&child,node->children); 113 114 childFilter->updateRef((char*)pParent + member->getMemberOffset()); 115 childFilter->put(); 116 node = setNextNode(node); 117 }; 118 //restore level to fkey node 119 if (member->getFKeyName() != NULL) 120 pNode = pNode->parent; 121 }; 122 pNode = setNextNode(pNode); 123 }; 124 }; 125 126 bool 127 XMLIStream::get(CollectionFilterBase* pFilter, const char* pRootTable) { 128 bool ret = false; 129 130 Storeable& parent(pFilter->create()); 131 //FIXME should find first node named pRootTable from current node 132 //FIXME open shuold find first node with id equal to parent.getId() (if set); 133 open(parent,pRootTable); 134 135 while(mCurrentNode != NULL) { 136 137 //fill object data from attributes 138 applyFilters(&parent); 139 140 //traverse on xml child nodes and try to find members from 141 //collection tables 142 getChildren(&parent,mCurrentNode->children); 143 pFilter->put(); 144 ret = true; 145 146 //if object has id then finish, else continue adding next objects to filter 147 if (!parent.isNew()) 148 break; 149 mCurrentNode = setNextNode(mCurrentNode); 150 }; 151 return ret; 152 }; 153 154 void 155 XMLIStream::applyFilters(Storeable* pObject) { 45 156 const StoreTable* tbl = Stream::getTable(*pObject); 46 157 const char* current_table_name = tbl->getTableName(); … … 71 182 }; 72 183 updateVars(); 73 setNextNode(); 184 }; 185 186 bool 187 XMLIStream::getNext(Storeable* pObject) { 188 if (mCurrentNode == NULL) 189 return false; 190 applyFilters(pObject); 191 mCurrentNode = setNextNode(mCurrentNode); 74 192 return true; 75 193 }; trunk/dba/dba/xmlistream.h
r133 r138 22 22 Object input stream for XMLArchive 23 23 */ 24 class XMLIStream : public IStream, public XMLErrorHandler, public ConvSpecContainer {24 class XMLIStream : public IStream, public XMLErrorHandler, public ConvSpecContainer { 25 25 public: 26 26 XMLIStream(xmlNodePtr pNode, const ConvSpec& pSpecs); … … 30 30 virtual bool updateVars(); 31 31 virtual bool isCollectionFilterSupported() const { return true; }; 32 virtual bool get(Storeable* pObject, const char* pRootTable = NULL) { return IStream::get(pObject, pRootTable); } 33 virtual bool get(CollectionFilterBase* pFilter, const char* pRootTable = NULL); 32 34 virtual ~XMLIStream(); 33 35 private: … … 36 38 37 39 virtual void setIdsCondition(const char* pFKeyName, id pRelationId, const std::vector<id>& pIds); 38 void setNextNode(); 40 void applyFilters(Storeable* pObject); 41 xmlNodePtr setNextNode(xmlNodePtr pNode); 42 ColMemberEntry* findMember(Storeable* pObject, xmlNodePtr pNode); 43 ColMemberEntry* findNullMember(Storeable* pObject); 44 bool isClassMember(Storeable* pObject, xmlNodePtr pNode); 45 void getChildren(Storeable* pParent, xmlNodePtr pNode); 39 46 }; 40 47 trunk/dba/dba/xmlostream.cpp
r136 r138 100 100 }; 101 101 xmlAddChild(mParentNode, node); 102 }; 103 104 void 105 XMLOStream::initMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember) { 102 106 //set new parent node for storing subobjects 103 mParentNode = node;107 mParentNode = mParentNode->children; 104 108 }; 109 110 void 111 XMLOStream::endMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember) { 112 //parent node was set to point to valid parent object 113 //in hierarchy. After storing all children we have to reset it back to 114 //parent of pObject node 115 mParentNode = mParentNode->parent; 116 if (mParentNode == NULL) 117 throw DatabaseException("Internal error: parent node is NULL"); 118 }; 119 105 120 106 121 std::vector<id> … … 117 132 118 133 bool 119 XMLOStream::putChildren(Storeable* pObject) { 120 bool ret = OStream::putChildren(pObject); 121 //parent node was set in store() to point to valid parent object 122 //in hierarchy. After storing all children we have to reset it back to 123 //parent of pObject node 124 mParentNode = mParentNode->parent; 125 if (mParentNode == NULL) 126 throw DatabaseException("Internal error: parent node is NULL"); 127 }; 128 129 bool 130 XMLOStream::putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 134 XMLOStream::putMemberChildren(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 131 135 bool was_changed = false; 132 136 bool ret = false; 133 137 if (!pObject->isDeleted()) { 138 if (pMember.getFKeyName() != NULL) { 139 xmlAddChild(mParentNode, xmlNewNode(NULL, (xmlChar*)pMember.getFKeyName())); 140 mParentNode = mParentNode->children; 141 }; 134 142 std::auto_ptr<CollectionFilterIterator> iterator(pFilter.createIterator()); 135 143 while(iterator->hasNext()) { … … 140 148 }; 141 149 iterator->moveForward(); 150 }; 151 if (pMember.getFKeyName() != NULL) { 152 mParentNode = mParentNode->parent; 142 153 }; 143 154 }; trunk/dba/dba/xmlostream.h
r136 r138 37 37 virtual bool store(Storeable* pObject); 38 38 virtual bool isCollectionFilterSupported() const { return true; }; 39 virtual bool putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName); 40 virtual bool putChildren(Storeable* pObject); 39 virtual bool putMemberChildren(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName); 41 40 virtual std::vector<id> loadRefData(const char* pTable, const char* pFkName, id pCollId, id pId); 42 41 virtual bool deleteRefData(const std::vector<id>& pIds, const char* pTableName); 42 virtual void initMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember); 43 virtual void endMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember); 43 44 private: 44 45 xmlNodePtr mParentNode; trunk/dba/test/testobject.h
r136 r138 314 314 }; 315 315 bool operator==(const ObjWithList& pObj) const { 316 if (mName != pObj.mName) return false; 317 if (mList.size() != pObj.mList.size()) 318 return false; 316 if (mName != pObj.mName) { 317 std::cerr << "Name mismatch. (mine:[" << mName << "], pObj:[" << pObj.mName << "])" << std::endl; 318 return false; 319 }; 320 if (mList.size() != pObj.mList.size()) { 321 std::cerr << "lists have different size (mine: " << mList.size() << ", pObj:" << pObj.mList.size() << ")" << std::endl; 322 return false; 323 }; 319 324 for(std::list<TestObject>::const_iterator it = mList.begin(); it != mList.end(); it++) { 320 325 std::list<TestObject>::const_iterator ot = std::find(pObj.mList.begin(), pObj.mList.end(), *it); trunk/dba/test/xmltestcase.cpp
r136 r138 126 126 dba::XMLIStream stream(ar.getIStream()); 127 127 stream.open(obj1); 128 CPPUNIT_ASSERT(!stream.get (&obj1));128 CPPUNIT_ASSERT(!stream.getNext(&obj1)); 129 129 }; 130 130 … … 180 180 181 181 void 182 XMLTestCase::sublist_one() { 183 const char* result = 184 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 185 "<dba>\n" 186 " <obj_with_list name=\"sub\">\n" 187 " <test_objects i_value=\"0\" f_value=\"0\" s_value=\"test_object\" d_value=\"2008-01-01Z00:00:00\"/>\n" 182 XMLTestCase::sublist_one_store() { 183 const char* result = 184 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 185 "<dba>\n" 186 " <obj_with_list name=\"sub\">\n" 187 " <fk_owner>\n" 188 " <test_objects i_value=\"0\" f_value=\"0\" s_value=\"test_object\" d_value=\"2008-01-01Z00:00:00\"/>\n" 189 " </fk_owner>\n" 188 190 " </obj_with_list>\n" 189 191 "</dba>\n"; … … 200 202 }; 201 203 204 void 205 XMLTestCase::sublist_two_store() { 206 const char* result = 207 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 208 "<dba>\n" 209 " <obj_with_list name=\"sub\">\n" 210 " <fk_owner>\n" 211 " <test_objects i_value=\"0\" f_value=\"0\" s_value=\"test_object\" d_value=\"2008-01-01Z00:00:00\"/>\n" 212 " <test_objects i_value=\"1\" f_value=\"1\" s_value=\"test_object\" d_value=\"2008-01-02Z00:00:00\"/>\n" 213 " </fk_owner>\n" 214 " </obj_with_list>\n" 215 "</dba>\n"; 216 { 217 dba::XMLArchive ar; 218 unlink("sublist_two.xml"); 219 ar.open("sublist_two.xml"); 220 ObjWithList obj1("sub",2); 221 dba::XMLOStream stream(ar.getOStream()); 222 stream.open(); 223 stream.put(&obj1); 224 } 225 CPPUNIT_ASSERT(compareXML("sublist_two.xml",result)); 226 }; 227 228 229 void 230 XMLTestCase::sublist_one_load() { 231 const char* data = 232 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 233 "<dba>\n" 234 " <obj_with_list name=\"sub\">\n" 235 " <fk_owner>\n" 236 " <test_objects i_value=\"0\" f_value=\"0\" s_value=\"test_object\" d_value=\"2008-01-01Z00:00:00\"/>\n" 237 " </fk_owner>\n" 238 " </obj_with_list>\n" 239 "</dba>\n"; 240 { 241 std::ofstream file("sublist_one_load.xml"); 242 file << data; 243 }; 244 { 245 dba::XMLArchive ar; 246 ar.open("sublist_one_load.xml"); 247 ObjWithList obj1; 248 dba::XMLIStream stream(ar.getIStream()); 249 250 /* std::cerr << &(obj1) << std::endl; 251 std::cerr << &(obj1.mList) << std::endl;*/ 252 stream.get(&obj1); 253 254 ObjWithList expected("sub",1); 255 256 CPPUNIT_ASSERT(obj1 == expected); 257 }; 258 }; 259 260 void 261 XMLTestCase::sublist_two_load() { 262 const char* data = 263 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 264 "<dba>\n" 265 " <obj_with_list name=\"sub\">\n" 266 " <fk_owner>\n" 267 " <test_objects i_value=\"0\" f_value=\"0\" s_value=\"test_object\" d_value=\"2008-01-01Z00:00:00\"/>\n" 268 " <test_objects i_value=\"1\" f_value=\"1\" s_value=\"test_object\" d_value=\"2008-01-02Z00:00:00\"/>\n" 269 " </fk_owner>\n" 270 " </obj_with_list>\n" 271 "</dba>\n"; 272 { 273 std::ofstream file("sublist_one_load.xml"); 274 file << data; 275 }; 276 { 277 dba::XMLArchive ar; 278 ar.open("sublist_one_load.xml"); 279 ObjWithList obj1; 280 dba::XMLIStream stream(ar.getIStream()); 281 282 /* std::cerr << &(obj1) << std::endl; 283 std::cerr << &(obj1.mList) << std::endl;*/ 284 stream.get(&obj1); 285 286 ObjWithList expected("sub",2); 287 288 CPPUNIT_ASSERT(obj1 == expected); 289 }; 290 }; 291 202 292 203 293 } //namespace trunk/dba/test/xmltestcase.h
r136 r138 33 33 CPPUNIT_TEST(simpleLoad); 34 34 CPPUNIT_TEST(varLoad); 35 CPPUNIT_TEST(sublist_one); 35 CPPUNIT_TEST(sublist_one_store); 36 CPPUNIT_TEST(sublist_two_store); 37 CPPUNIT_TEST(sublist_one_load); 38 CPPUNIT_TEST(sublist_two_load); 36 39 CPPUNIT_TEST_SUITE_END(); 37 40 public: … … 48 51 void simpleLoad(); 49 52 void varLoad(); 50 void sublist_one(); 53 void sublist_one_store(); 54 void sublist_two_store(); 55 void sublist_one_load(); 56 void sublist_two_load(); 51 57 private: 52 58 bool compareXML(const char* pFilename, const char* pData);
