Changeset 138

Show
Ignore:
Timestamp:
05/23/08 19:42:21 (8 months ago)
Author:
zork
Message:

xml load and store of simple objects with single sublist

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dba/dba/ostream.cpp

    r136 r138  
    4545 
    4646bool 
    47 OStream::putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 
     47OStream::putMemberChildren(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 
    4848  bool ret = false; 
    4949  bool was_changed = false; 
     
    126126      const char* obj_table = member->getTableName(); 
    127127      //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); 
    129131      if (!ret) ret = was_changed; 
    130132      //move forward in loop 
  • trunk/dba/dba/ostream.h

    r136 r138  
    6868    virtual ~OStream() {}; 
    6969  protected: 
     70    virtual void initMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember) {}; 
     71    virtual void endMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember) {}; 
    7072    /** 
    7173      Default implementation for BIND_COL store that works on data stored in relations and  
     
    7880      @return true if at least one subobject object was stored in archive, false otherwise 
    7981    */ 
    80     virtual bool putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName); 
     82    virtual bool putMemberChildren(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName); 
    8183    /** 
    8284      Store all Storeable objects on sublists listed as BIND_COL in store table 
  • trunk/dba/dba/xmlistream.cpp

    r133 r138  
    1111// 
    1212#include "xmlistream.h" 
     13#include "collectionfilter.h" 
     14#include <iostream> 
    1315 
    1416namespace dba { 
     
    1921    mParentNode(pNode) 
    2022{ 
    21   mCurrentNode = mParentNode->children; 
    22   setNextNode(); 
     23  mCurrentNode = setNextNode(mParentNode->children); 
    2324} 
    2425 
    25 void 
    26 XMLIStream::setNextNode() { 
    27   while( mCurrentNode && xmlIsBlankNode(mCurrentNode) == 1) 
    28     mCurrentNode = mCurrentNode->next; 
     26xmlNodePtr 
     27XMLIStream::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; 
    2936}; 
    3037 
     
    3946}; 
    4047 
    41 bool  
    42 XMLIStream::getNext(Storeable* pObject) { 
    43   if (mCurrentNode == NULL) 
    44     return false; 
     48ColMemberEntry* 
     49XMLIStream::findNullMember(Storeable* pObject) { 
     50  return findMember(pObject, NULL); 
     51}; 
     52 
     53ColMemberEntry* 
     54XMLIStream::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 
     73bool 
     74XMLIStream::isClassMember(Storeable* pObject, xmlNodePtr pNode) { 
     75  //TODO check store table and find membe with the same name as pNode 
     76  return false; 
     77}; 
     78 
     79void 
     80XMLIStream::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 
     126bool 
     127XMLIStream::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 
     154void 
     155XMLIStream::applyFilters(Storeable* pObject) { 
    45156  const StoreTable* tbl = Stream::getTable(*pObject); 
    46157  const char* current_table_name = tbl->getTableName(); 
     
    71182  }; 
    72183  updateVars(); 
    73   setNextNode(); 
     184}; 
     185 
     186bool  
     187XMLIStream::getNext(Storeable* pObject) { 
     188  if (mCurrentNode == NULL) 
     189    return false; 
     190  applyFilters(pObject); 
     191  mCurrentNode = setNextNode(mCurrentNode); 
    74192  return true; 
    75193}; 
  • trunk/dba/dba/xmlistream.h

    r133 r138  
    2222Object input stream for XMLArchive 
    2323*/ 
    24 class XMLIStream : public IStream, public XMLErrorHandler, public ConvSpecContainer { 
     24class XMLIStream : public IStream, public XMLErrorHandler, public ConvSpecContainer { 
    2525  public: 
    2626    XMLIStream(xmlNodePtr pNode, const ConvSpec& pSpecs); 
     
    3030    virtual bool updateVars(); 
    3131    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); 
    3234    virtual ~XMLIStream(); 
    3335  private: 
     
    3638     
    3739    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); 
    3946}; 
    4047 
  • trunk/dba/dba/xmlostream.cpp

    r136 r138  
    100100  }; 
    101101  xmlAddChild(mParentNode, node); 
     102}; 
     103 
     104void  
     105XMLOStream::initMemberChildrenStore(const Storeable& pObject, const ColMemberEntry& pMember) { 
    102106  //set new parent node for storing subobjects 
    103   mParentNode = node
     107  mParentNode = mParentNode->children
    104108}; 
     109 
     110void  
     111XMLOStream::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 
    105120 
    106121std::vector<id>  
     
    117132 
    118133bool  
    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) { 
     134XMLOStream::putMemberChildren(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 
    131135  bool was_changed = false; 
    132136  bool ret = false; 
    133137  if (!pObject->isDeleted()) { 
     138    if (pMember.getFKeyName() != NULL) { 
     139      xmlAddChild(mParentNode, xmlNewNode(NULL, (xmlChar*)pMember.getFKeyName())); 
     140      mParentNode = mParentNode->children; 
     141    }; 
    134142    std::auto_ptr<CollectionFilterIterator> iterator(pFilter.createIterator()); 
    135143    while(iterator->hasNext()) { 
     
    140148      }; 
    141149      iterator->moveForward(); 
     150    }; 
     151    if (pMember.getFKeyName() != NULL) { 
     152      mParentNode = mParentNode->parent; 
    142153    }; 
    143154  }; 
  • trunk/dba/dba/xmlostream.h

    r136 r138  
    3737    virtual bool store(Storeable* pObject); 
    3838    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); 
    4140    virtual std::vector<id> loadRefData(const char* pTable, const char* pFkName, id pCollId, id pId); 
    4241    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); 
    4344  private: 
    4445    xmlNodePtr mParentNode; 
  • trunk/dba/test/testobject.h

    r136 r138  
    314314    }; 
    315315    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      }; 
    319324      for(std::list<TestObject>::const_iterator it = mList.begin(); it != mList.end(); it++) { 
    320325        std::list<TestObject>::const_iterator ot = std::find(pObj.mList.begin(), pObj.mList.end(), *it); 
  • trunk/dba/test/xmltestcase.cpp

    r136 r138  
    126126  dba::XMLIStream stream(ar.getIStream()); 
    127127  stream.open(obj1); 
    128   CPPUNIT_ASSERT(!stream.get(&obj1)); 
     128  CPPUNIT_ASSERT(!stream.getNext(&obj1)); 
    129129}; 
    130130 
     
    180180 
    181181void  
    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" 
     182XMLTestCase::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" 
    188190"  </obj_with_list>\n" 
    189191"</dba>\n"; 
     
    200202}; 
    201203 
     204void  
     205XMLTestCase::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 
     229void  
     230XMLTestCase::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 
     260void  
     261XMLTestCase::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 
    202292 
    203293} //namespace 
  • trunk/dba/test/xmltestcase.h

    r136 r138  
    3333      CPPUNIT_TEST(simpleLoad); 
    3434      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); 
    3639    CPPUNIT_TEST_SUITE_END(); 
    3740  public: 
     
    4851    void simpleLoad(); 
    4952    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(); 
    5157  private: 
    5258    bool compareXML(const char* pFilename, const char* pData);