Changeset 164

Show
Ignore:
Timestamp:
07/18/08 13:26:14 (6 months ago)
Author:
zork
Message:

xmlistream reimplemented

Files:

Legend:

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

    r160 r164  
    3737Stream::Stream()  
    3838  : mRootTable(NULL), 
    39     mMemberList(new mt_mlist())   
     39    mMemberList(new mt_mlist()), 
     40    mDebugFlag(false) 
    4041{ 
    4142  mIsOpen = false; 
     
    183184}; 
    184185 
     186const char*  
     187Stream::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}; 
    185199 
    186200void 
  • trunk/dba/dba/stream.h

    r162 r164  
    173173    */ 
    174174    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); 
    175180    /** 
    176181      Get root collection table for object 
  • trunk/dba/dba/xmlistream.cpp

    r154 r164  
    1313#include "xmlutils.h" 
    1414#include "collectionfilter.h" 
    15 #include <iostream> 
     15#include <sstream> 
    1616 
    1717namespace dba { 
     
    5252}; 
    5353 
    54 ColMemberEntry* 
    55 XMLIStream::findNullMember(Storeable* pObject) { 
    56   return findMember(pObject, NULL); 
    57 }; 
    58  
    59 ColMemberEntry* 
    60 XMLIStream::findMember(Storeable* pObject, xmlNodePtr pNode) { 
     54void 
     55XMLIStream::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 
     77void 
     78XMLIStream::getChildren(Storeable* pObject, xmlNodePtr pNode) { 
     79  pNode = findNonTextNode(pNode); 
    6180  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(); 
    73104      }; 
    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(); 
    130106    }; 
    131107    pNode = setNextNode(pNode); 
     
    137113  bool ret = false; 
    138114 
    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) { 
    144126   
    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   
    150131    //traverse on xml child nodes and try to find members from  
    151132    //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); 
    154136    ret = true; 
    155137 
    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); 
    160140  }; 
    161141  return ret; 
     142}; 
     143 
     144xmlNsPtr 
     145XMLIStream::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; 
    162160}; 
    163161 
    164162xmlAttrPtr 
    165163XMLIStream::findAttribute(xmlNodePtr pNode, const char* pMemberName) { 
    166   char* ns = XMLUtils::getNsFromName(pMemberName); 
    167  
    168164  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 { 
    177169    char* name = XMLUtils::getNameWithoutNs(pMemberName); 
    178170    ret = xmlHasNsProp(pNode,(xmlChar*)name,nsptr->href); 
    179171    delete [] name; 
     172  }; 
     173  return ret; 
     174}; 
     175 
     176xmlNodePtr  
     177XMLIStream::findNode(xmlNodePtr pNode, const char* pName) { 
     178  xmlNsPtr nsptr = getXMLNamespace(pName, pNode); 
     179  xmlChar* name = NULL; 
     180  if (nsptr == NULL) { 
     181    name = (xmlChar*)pName; 
    180182  } 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 
     198void  
     199XMLIStream::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)"); 
    185205}; 
    186206 
    187207void 
    188 XMLIStream::applyFilters(Storeable* pObject) { 
     208XMLIStream::applyFilters(Storeable* pObject, xmlNodePtr pNode) { 
    189209  const StoreTable* tbl = Stream::getTable(*pObject); 
    190210  const char* current_table_name = tbl->getTableName(); 
    191211  if (current_table_name == NULL) 
    192212    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); 
    193214  while(tbl != NULL) { 
    194215    if (tbl->getTableName() != NULL) 
     
    198219      dba::StoreableFilterBase* filter(member->getFilter()); 
    199220      setFilterPtr(*filter,(char*)pObject + (int)(member->getMemberOffset() + tbl->getClassOffset())); 
    200       xmlAttrPtr attr = findAttribute(mCurrentNode,member->getMemberName()); 
     221      xmlAttrPtr attr = findAttribute(pNode,member->getMemberName()); 
    201222      if (attr != NULL) { 
    202223        xmlChar* xmldata = xmlNodeGetContent(attr->children); 
     
    221242  if (mCurrentNode == NULL) 
    222243    return false; 
    223   applyFilters(pObject); 
     244  applyFilters(pObject,mCurrentNode); 
    224245  mCurrentNode = setNextNode(mCurrentNode); 
    225246  return true; 
     
    227248 
    228249bool  
    229 XMLIStream::updateVars() { 
     250XMLIStream::updateVars(xmlNodePtr pNode) { 
    230251  if (mCurrentNode == NULL) 
    231252    return false; 
    232253  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)) { 
    234255      xmlAttrPtr attr = findAttribute(mCurrentNode, it->mField); 
    235256      dba::StoreableFilterBase& filter(*(it->mFilter)); 
  • trunk/dba/dba/xmlistream.h

    r155 r164  
    4242    virtual void destroy(); 
    4343    virtual bool getNext(Storeable* pObject); 
    44     virtual bool updateVars(); 
     44    virtual bool updateVars() { return updateVars(mCurrentNode); } 
    4545    virtual bool isCollectionFilterSupported() const { return true; }; 
    4646    virtual bool get(Storeable* pObject, const char* pRootTable = NULL) { return IStream::get(pObject, pRootTable); } 
     
    5555     
    5656    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); 
    5859    xmlNodePtr setNextNode(xmlNodePtr pNode); 
    5960    xmlNodePtr findNonTextNode(xmlNodePtr pNode); 
    60     ColMemberEntry* findMember(Storeable* pObject, xmlNodePtr pNode); 
    61     ColMemberEntry* findNullMember(Storeable* pObject); 
    62     bool isClassMember(Storeable* pObject, xmlNodePtr pNode); 
    6361    void getChildren(Storeable* pParent, xmlNodePtr pNode); 
     62    void updateCollection(Storeable* pParent, ColMemberEntry* pEntry, xmlNodePtr pNode); 
    6463    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); 
    6567}; 
    6668 
  • trunk/dba/test/main.cpp

    r157 r164  
    148148  //runner.addTest(new CppUnit::TestCaller<PostgresSQLArchiveTestCase>("debug_test",&PostgresSQLArchiveTestCase::sqlError)); 
    149149  //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)); 
    151151  //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)); 
    154154  //runner.addTest(new CppUnit::TestCaller<dba_tests::XMLTestCase>("debug_test",&dba_tests::XMLTestCase::store_two)); 
    155155  //runner.addTest(new CppUnit::TestCaller<OdbcPluginTestCase>("debug_test",&OdbcPluginTestCase::dbConnection)); 
  • trunk/dba/test/xmltestcase.cpp

    r159 r164  
    259259"  <obj_with_list name=\"sub\">\n" 
    260260"    <fk_owner>\n" 
     261"      <test_objects i_value=\"1\" f_value=\"1\" s_value=\"test_object\" d_value=\"2008-01-02Z00:00:00\"/>\n" 
    261262"      <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" 
    263263"    </fk_owner>\n" 
    264264"  </obj_with_list>\n" 
     
    661661} 
    662662 
     663class 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 
     671BEGIN_STORE_TABLE(SecondSingle,TestObject,"secondsingle") 
     672END_STORE_TABLE() 
     673 
    663674class TwoSingles : public dba::Storeable { 
    664675    DECLARE_STORE_TABLE(); 
     
    668679      : mName(pName), 
    669680        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))) 
    671682    {}; 
    672683    bool operator==(const TwoSingles& pObj) { 
     
    677688    std::string mName; 
    678689    TestObject mObj1; 
    679     TestObject mObj2;   
     690    SecondSingle mObj2;   
    680691}; 
    681692 
     
    693704"  <twosingles parent=\"parent_name\">\n" 
    694705"    <test_objects i_value=\"1\" f_value=\"1\" s_value=\"1\" d_value=\"2008-01-01Z00:00:00\"/>\n" 
    695 "    <test_objects i_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" 
    696707"  </twosingles>\n" 
    697708"</dba>\n" 
     
    708719    TwoSingles loaded; 
    709720    dba::XMLIStream stream(xmlArch.getIStream()); 
     721    //stream.enableDebug(); 
    710722    stream.get(&loaded); 
    711723    CPPUNIT_ASSERT(loaded == expected);