]> Creatis software - creaImageIO.git/blobdiff - src2/creaImageIOSQLiteTreeHandler.cpp
For a given file, display all dicom tags.
[creaImageIO.git] / src2 / creaImageIOSQLiteTreeHandler.cpp
index 509aa90429e4c1f3e9e4447bc7f5f522a88f9e2d..e9724c40d63d731096ea697d7757953b6c362446 100644 (file)
@@ -1,30 +1,19 @@
 #include <creaImageIOSQLiteTreeHandler.h>
+#include <creaImageIOSystem.h>
+#include <creaImageIOGimmick.h>
+#include <creaImageIOTree.h>
 
 #include "CppSQLite3.h"
 
 #include <sys/stat.h>
 
-//#include <creaImageIOSQLiteTreeHandlerStructure.h>
-
-//#include <creaImageIOUtilities.h>
-
-//#include <icons/database.xpm>
-
 #include <deque>
 
-#include "wx/wx.h"
-#include <wx/dir.h>
-#include <wx/filename.h>
-
-
-//#include <icons/close.xpm>
-
 #include <creaWx.h>
-#include <creaMessageManager.h>
+#include <boost/algorithm/string.hpp>
 using namespace crea;
 
-#include <boost/filesystem.hpp>
-#include <boost/algorithm/string/replace.hpp>
+
 
 namespace creaImageIO
 {
@@ -35,28 +24,9 @@ namespace creaImageIO
   SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename)
     : mFileName(filename)
   {
-    /*
-    mSQLiteTreeHandler = this;
-    NodeTypeDescription::FieldDescriptionMapType& M = 
-      mNodeTypeDescription[Node::Database].GetFieldDescriptionMap();
-
-    boost::filesystem::path full_path(location);
-    mName = full_path.leaf();
-    Field::Description fname("Name",0,0,"Name",0);
-    M[fname.key] = fname;
-    UnsafeSetFieldValue(fname.key,mName);
-    Field::Description flocation("File name",0,0,"File name",0);
-    M[flocation.key] = flocation;
-    UnsafeSetFieldValue(flocation.key,location);
-    */
-    //    Field::Description ftype("Type",0,0,"Type",0);
-    //    M[ftype.key] = ftype;
-    //    UnsafeSetFieldValue(ftype.key,"Invalid location");
-
     mDB = new CppSQLite3DB;
-    //    std::cout << "** SQLite Version: " << mDB->SQLiteVersion() << std::endl;
-
-
+       mIsAdding=false;
+    //GimmickMessage(1,"SQLite version : "                <<std::string(mDB->SQLiteVersion())<< std::endl);
   }
   //=============================================================
 
@@ -64,101 +34,12 @@ namespace creaImageIO
   SQLiteTreeHandler::~SQLiteTreeHandler()
   {
     delete mDB;
-    /*
-      Already done in Node now that SQLiteTreeHandler inherits from it
-    ChildrenListType::iterator i;
-    for (i=GetChildrenList().begin(); i!=GetChildrenList().end(); i++)
-      {
-       delete *i;
-      }
-    */
   }
   //=============================================================
   
 
-  //=============================================================
-  void SQLiteTreeHandler::BuildDefaultTreeDescription()
-  {
-    /*
-    for (int i = Node::Patient;
-        i <= Node::Image; 
-        ++i)
-      {
-       mNodeTypeDescription[i].BuildDefault(i);
-      }
-    */
-
-    // TODO : GetTree().GetDescription().LoadXML(FILE);
-  }
-  //=============================================================
-
-  //=============================================================
-  //  void SQLiteTreeHandler::Print() const 
-  //  {
-    /*
-    std::cout << "-> '"<<GetName()<< "' - '"
-             << GetFileName()<<"'"<<std::endl;
-    ChildrenListType::const_iterator i;
-    for (i=GetChildrenList().begin(); i!=GetChildrenList().end(); i++)
-      {
-       (*i)->Print();
-      }
-    */
-  //  }
-  //=============================================================
-  
-  //=====================================================================
-  /*
-  bool SQLiteTreeHandler::LocationIsValid()
-  {
-    // TO DO 
-    return true;
-  }
-  */
-  //=====================================================================
-
   //=====================================================================
-  char* format_sql(const std::string& s)
-  { 
-    return sqlite3_mprintf("%q",s.c_str());
-  }
-  //=====================================================================
-
-  //  sqlite3_exec(db, zSQL, 0, 0, 0);
-  //  sqlite3_free(zSQL);
-  //   char* CHAIN = format_sql(QUER);         \
-//  sqlite3_free(CHAIN);                               \
 
-  //=====================================================================
-#define QUERYDB(QUER,RES)                                              \
-    try                                                                        \
-      {                                                                        \
-       RES = mDB->execQuery(QUER.c_str());                             \
-      }                                                                        \
-    catch (CppSQLite3Exception& e)                                     \
-      {                                                                        \
-       std::cout << "SQLite query '"<<QUER<<"' : "<< e.errorCode() << ":" \
-                 << e.errorMessage()<<std::endl;                       \
-       creaError("SQLite query '"<<QUER<<"' : "<< e.errorCode() << ":" \
-                  << e.errorMessage() );                               \
-      }                                                                        \
-    
-  //=====================================================================
-  
-  //=====================================================================
-#define UPDATEDB(UP)                                                   \
-  try                                                                  \
-    {                                                                  \
-      mDB->execDML(UP.c_str());                                                \
-    }                                                                  \
-  catch (CppSQLite3Exception& e)                                       \
-    {                                                                  \
-      std::cout << "SQLite update '"<<UP<<"' Error : "<< e.errorCode() << ":" \
-               << e.errorMessage()<<std::endl;                         \
-      creaError("SQLite update '"<<UP<<"' Error : "<< e.errorCode() << ":" \
-                << e.errorMessage() );                                 \
-    }                                                                  
-  //=====================================================================
 
   //=====================================================================
   bool SQLiteTreeHandler::Open(bool writable)
@@ -181,7 +62,7 @@ namespace creaImageIO
   //=====================================================================
   bool SQLiteTreeHandler::Close()
   {
-    return false;
+    return true;
   }
   //=====================================================================
 
@@ -191,19 +72,14 @@ namespace creaImageIO
   {
     return false;
   }
-  //=====================================================================
-
-  //===================================================================== 
-  unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
-  { 
-    return 0; 
-  }
+  
   //===================================================================== 
 
   //===================================================================== 
   int SQLiteTreeHandler::LoadChildren(tree::Node* parent, int maxlevel)
   {
-    return 0;
+    if (parent==0) parent = GetTree().GetTree();
+    return DBLoadChildren(parent,maxlevel);
   }
   //===================================================================== 
 
@@ -216,20 +92,78 @@ namespace creaImageIO
   }
   //===================================================================== 
 
-
   //===================================================================== 
-  int SQLiteTreeHandler::AddBranch( const std::map<std::string,std::string>& attr )
+  int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr )
   {
-    return -1;
+    tree::Node* parent = DBGetParent(attr);
+    DBGraftToParent(parent,attr);
+    return (parent->GetLevel()+1);
+         
   }
   //===================================================================== 
  
 
   //===================================================================== 
-   bool SQLiteTreeHandler::Remove(tree::Node*)
+   bool SQLiteTreeHandler::Remove(tree::Node* node)
    {
-     return false;
+   DBRecursiveRemoveNode(node);
+    //    std::cout << "DELETE"<<std::endl;
+   bool remove=false;
+   tree::Node* parent=node->GetParent();
+    if (parent)
+      {
+       int nC = parent->RemoveChildrenFromList(node);
+       if(nC>0 && parent->GetLevel()>0)
+       {       
+               std::stringstream out;
+               out <<nC;
+               SetAttribute(parent,"NumberOfChildren",out.str());
+       }
+       else
+       {
+               remove=true;
+       }
+
+      }
+    delete node;
+       if(remove&&parent->GetLevel()>0)
+       {
+               Remove(parent);
+       }
+    //    std::cout << "DELETE OK"<<std::endl;
+    return true;
    }
+  
+  //===================================================================== 
+
+  //===================================================================== 
+  /// Sets an attribute of a Node
+  bool SQLiteTreeHandler::SetAttribute(tree::Node* n, 
+                                      const std::string& key,
+                                      const std::string& value)
+  {
+    if (n==0) n=GetTree().GetTree();
+    return DBSetAttribute(n,key,value);
+  }
+  //===================================================================== 
+   //===================================================================== 
+  /// Sets an attribute
+  void SQLiteTreeHandler::SetAttribute(const std::string& levelDescriptor, 
+                             const std::string& key,
+                             const std::string& value,
+                                 const std::string& searchParam, 
+                                 const std::string& searchVal)
+  {
+       DBSetAttribute(levelDescriptor,key,value,searchParam, searchVal);
+  }
+  //===================================================================== 
+  /// Deletes a tuple
+  void SQLiteTreeHandler::DeleteTuple(std::string levelDescriptor, 
+                                                               std::string key, std::string value)
+  {
+    DBDelete(levelDescriptor,key,value);
+  }
   //===================================================================== 
 
 
@@ -238,10 +172,64 @@ namespace creaImageIO
 
 
 
+
+
+
+
+
+
+  //=====================================================================
+  // SQLite DB specific methods
+  //=====================================================================
+
+
+
+
+  //=====================================================================
+  char* format_sql(const std::string& s)
+  { 
+    return sqlite3_mprintf("%q",s.c_str());
+  }
+  //=====================================================================
+
+  
+  //=====================================================================
+#define QUERYDB(QUER,RES)                                              \
+    try                                                                        \
+      {                                                                        \
+       GimmickMessage(2,"SQL query: '"<<QUER<<"'"<<std::endl);         \
+       RES = mDB->execQuery(QUER.c_str());                             \
+      }                                                                        \
+    catch (CppSQLite3Exception& e)                                     \
+      {                                                                        \
+       GimmickError("SQLite query '"<<QUER<<"' : "                     \
+                    << e.errorCode() << ":"                            \
+                    << e.errorMessage() );                             \
+      }                                                                        \
+    
+  //=====================================================================
+  
+  //=====================================================================
+#define UPDATEDB(UP)                                                   \
+  try                                                                  \
+    {                                                                  \
+      GimmickMessage(2,"SQL update: '"<<UP<<"'"<<std::endl);           \
+      mDB->execDML(UP.c_str());                                                \
+    }                                                                  \
+  catch (CppSQLite3Exception& e)                                       \
+    {                                                                  \
+      GimmickError("SQLite update '"<<UP<<"' Error : "                 \
+                  << e.errorCode() << ":"                              \
+                  << e.errorMessage() );                               \
+    }                                                                  
+  //=====================================================================
+
+
   //=====================================================================
   bool SQLiteTreeHandler::DBOpen()
   {
-    //    std::cout << "### Opening SQLite database '"<<GetFileName()<<std::endl;
+    GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
+                  <<"' ... "<<std::endl);
     // OPENING FILE
     if (!boost::filesystem::exists(GetFileName())) 
       {
@@ -254,20 +242,19 @@ namespace creaImageIO
       }
     catch (CppSQLite3Exception& e)
       {
-       std::cerr << "Opening '"<<GetFileName()<<"' : "
-                 << e.errorCode() << ":" 
-                 << e.errorMessage() << std::endl;
+       GimmickError("Opening '"<<GetFileName()<<"' : "
+                    << e.errorCode() << ":" 
+                    << e.errorMessage());
        return false;
       }
-    // TESTING STRUCTURE VALIDITY
-    if (!DBStructureIsValid())
+    // IMPORT TREE DESCRIPTION (AND TEST DB VALIDITY)
+    if (!DBImportTreeDescription())
       {
-       std::cerr << "Opening '"<<GetFileName()<<"' : "
-                 << " invalid database structure" << std::endl;
        return false;
       }
-    // IMPORTING NODE TYPE DESCRIPTIONS
-    DBImportTreeDescription();
+
+    GimmickDebugMessage(1,"Opening SQLite database '"<<GetFileName()
+                  <<"' ... OK"<<std::endl);
     return true;
   }
   //=====================================================================
@@ -275,13 +262,13 @@ namespace creaImageIO
   //=====================================================================
   bool SQLiteTreeHandler::DBCreate()
   {
-    //    std::cout << "### Creating SQLite database '"<<GetFileName()<<std::endl;
+    GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
+                  <<"' ... "<<std::endl);
 
     if (boost::filesystem::exists(GetFileName())) 
       {
-       creaMessage("Gimmick!",1,
-                   "[Gimmick!] !! ERROR '"<<GetFileName()<<"' : "
-                   << "file already exists"<<std::endl);
+       GimmickError(GetFileName()<<"' : "
+                    << "file already exists");
        return false;
       }
     
@@ -292,688 +279,738 @@ namespace creaImageIO
       }
     catch (CppSQLite3Exception& e)
       {
-       creaMessage("Gimmick!",1,
-                   "[Gimmick!] !! ERROR '"
-                   << e.errorCode() << ":" 
-                   << e.errorMessage() <<std::endl);
+       GimmickError(e.errorCode() << ":" 
+                    << e.errorMessage() <<std::endl);
        return false;
       }
     
+     
     // CREATING TABLES
-    try
-      {
-       std::string command;
-       // Level 0
-       command = "create table ";
-       command += GetTree().GetLevelDescriptor(0).GetName();
-       command += "\n(\nID INTEGER PRIMARY KEY,\n";
-       AppendAttributesSQLDefinition(0,command);
-       command += "\n)";
+    
+    std::string command;
+    // Create LEVELS table
+    command = "create table LEVELS\n";
+    command += "( Name text )\n";
+    UPDATEDB(command);
+    int l;
+    // Iterate the Levels
+    for (l=0; l<GetTree().GetNumberOfLevels(); l++)
+      {
+       command = "INSERT INTO LEVELS (Name) VALUES ('";
+       command += GetTree().GetLevelDescriptor(l).GetName();
+       command += "')";
        UPDATEDB(command);
        
-       // Iterate the other Levels
-       for (int l=1; l<GetTree().GetNumberOfLevels(); ++l)
-         {
-           command = "create table ";
-           command += GetTree().GetLevelDescriptor(l).GetName();
-           command += "\n(\nID INTEGER PRIMARY KEY,\nPARENT_ID int not null,\n";       
-           AppendAttributesSQLDefinition(l,command);
-           command +=",\n";
-           command +="constraint FK_PARENT foreign key (PARENT_ID) references PATIENT(ID) on delete restrict on update restrict\n)";
-           UPDATEDB(command);
-         }
-       
-       // Create tables *_ATTRIBUTES
-       for (int l=1; l<GetTree().GetNumberOfLevels(); ++l)
+       // Create table of level (for level>0, i.e. not Root)
+       if (l>=0)
          {
-           command = "create table ";
+           command = "CREATE TABLE ";
            command += GetTree().GetLevelDescriptor(l).GetName();
-           command += "_ATTRIBUTES\n(\n";
-           command += "Key text,\n";
-           command += "Group int,\n";
-           command += "Element int,\n";            
-           command += "Name text,\n";      
-           command += "Flags int\n";       
+           command += "\n(\nID INTEGER PRIMARY KEY";
+           if (l>1) 
+             {
+               command += ",\nPARENT_ID int not null"; 
+             }
+           SQLAppendAttributesDefinition(l,command);
+           if (l>1) 
+             {
+               command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
+               command += GetTree().GetLevelDescriptor(l-1).GetName();
+               command += "(ID) on delete restrict on update restrict";
+             }
            command += "\n)";
            UPDATEDB(command);
+           
+           
+           // Add Attribute 'ID' to Description
+           GetTree().GetDescriptor().Add
+             (AttributeDescriptor( "ID",
+                                   "Database Identifier",
+                                   0,0,
+                                   AttributeDescriptor::PRIVATE
+                                   ),l);
+           
+           if (l>1) 
+             {
+               // Add Attribute 'PARENT_ID' to Description
+               GetTree().GetDescriptor().Add
+                 (AttributeDescriptor( "PARENT_ID",
+                                       "Database Parent Identifier",
+                                       0,0,
+                                       AttributeDescriptor::PRIVATE
+                                       ),l);
+             }
+           
          }
-       // Fill the tables *_ATTRIBUTES
-       DBExportTreeDescription();
-       
-      }
-    catch (std::exception)
-      {
-       return false;
-      }
-    // LG : TEST
-    if (DBStructureIsValid())
-      {
-       //      std::cout << "*** DONE ***"<<std::endl;
-       //      mDBLoaded = true;
-       GetTree().SetChildrenLoaded(true);
-       return true;
        
-      }
-    else 
-      {
-       //      std::cout << "*** AAAARRRRGGG ***"<<std::endl;
+       // Create table *_ATTRIBUTES
        
-       return false;
-      }
+       command = "CREATE TABLE ";
+       command += GetTree().GetLevelDescriptor(l).GetName();
+       command += "_Attributes\n(\n";
+       command += "Key text,\n";
+       command += "Name text,\n";          
+       command += "DicomGroup int,\n";
+       command += "DicomElement int,\n";           
+       command += "Flags int\n";           
+       command += "\n)";
+       UPDATEDB(command);
+
+       // Fill the table *_ATTRIBUTES
+       LevelDescriptor::AttributeDescriptorListType::const_iterator i;
+       for (i  = GetTree().GetAttributeDescriptorList(l).begin();
+            i != GetTree().GetAttributeDescriptorList(l).end();
+            ++i)
+         {
+           
+           std::stringstream insert;
+           insert << "INSERT INTO "
+                  << GetTree().GetLevelDescriptor(l).GetName()
+                  << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
+                  << "VALUES ('"
+                  << i->GetKey() << "','"
+                  << i->GetName() << "',"
+                  << i->GetGroup() << ","
+                  << i->GetElement() << ","
+                  << i->GetFlags() << ");";
+           UPDATEDB(insert.str());
+         }
+
+      } // For l=0...
+
+    // Initialize the root attributes
+    GetTree().InitializeAttributeMap();
+    // Insert the root in the level 0 table 
+    DBInsert(GetTree().GetTree());
+    
+    
+    GetTree().SetChildrenLoaded(true);
+    GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
+                  <<"' ... OK"<<std::endl);
+    return true;
   }
   //=====================================================================
   
   //=====================================================================
-  void SQLiteTreeHandler::AppendAttributesSQLDefinition(int level,
+  void SQLiteTreeHandler::SQLAppendAttributesDefinition(int level,
                                                        std::string& s)
   {
-    /*
-    std::vector<std::string*> keys;
-    NodeTypeDescription::FieldDescriptionMapType::iterator i;
-    for (i  = GetNodeTypeDescription(c).GetFieldDescriptionMap().begin();
-        i != GetNodeTypeDescription(c).GetFieldDescriptionMap().end();
+    LevelDescriptor::AttributeDescriptorListType::const_iterator i;
+    for (i  = GetTree().GetAttributeDescriptorList(level).begin();
+        i != GetTree().GetAttributeDescriptorList(level).end();
         ++i)
       {
-       if (i->second.flags==1) continue;
-       keys.push_back(&(i->second.key));
-      }
-    std::vector<std::string*>::iterator j;
-    for (j=keys.begin();j!=keys.end();)
-      {
-       s += **j + " text";
-       ++j;
-       if (j!=keys.end())
-         s += ",\n";
+       //      if (i->second.flags==1) continue;
+       s += ",\n";
+       s += i->GetKey();
+       s += " text";
       }
-    */
   }
   //=====================================================================
   
-  //=====================================================================
-  void SQLiteTreeHandler::DBExportTreeDescription()
-  {
-    /*
-    //    std::cout<<"ExportNodeTypeDescriptionsToDB()"<<std::endl;
-    for (Node::Type type=Node::Patient; 
-        type<=Node::Image; 
-        type++)
-      {
-       NodeTypeDescription::FieldDescriptionMapType::iterator i;
-       for (i = GetNodeTypeDescription(type).GetFieldDescriptionMap().begin();
-            i!= GetNodeTypeDescription(type).GetFieldDescriptionMap().end();
-            i++)
-         {
-           
-           std::stringstream insert;
-           insert << "INSERT INTO "
-                  << std::string(SQLiteTreeHandlerStructure::Table(type))
-                  << "_FIELDS (Key,DicomGroup,DicomElement,Name,Flags) "
-                  << "VALUES ('"
-                  << (*i).second.GetKey() << "',"
-                  << (*i).second.GetGroup() << ","
-                  << (*i).second.GetElement() << ",'"
-                  << (*i).second.GetName() << "',"
-                  << (*i).second.GetFlags() << ");";
-
-           //      std::cout << "** SQL = '"<<insert.str()<<"'"<<std::endl;
-           
-           UPDATEDB(insert.str());
-         }
-      }
-    */
-  }
-  //=====================================================================
   
   //=====================================================================
-  void SQLiteTreeHandler::DBImportTreeDescription()
+  bool SQLiteTreeHandler::DBImportTreeDescription()
   {
-    //    std::cout<<"ImportNodeTypeDescriptionsFromDB()"<<std::endl;
-    /*
-    for (Node::Type type=Node::Patient; 
-        type<=Node::Image; 
-        type++)
+    GimmickMessage(1,"Importing tree description for database ..."
+                  <<std::endl);
+
+    // Test table 'LEVELS' existence
+    if ( ! mDB->tableExists("LEVELS") )
       {
-       std::string query = "SELECT * FROM ";
-       query += SQLiteTreeHandlerStructure::Table(type);
-       query += "_FIELDS";
+       GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist"
+                      <<std::endl);
+       return false;
+      }
+
+    tree::Descriptor& desc = GetTree().GetDescriptor();
+    // clears the existing one
+    desc.Clear();
+     
+    int nblevel = 0;
+    std::string query = "SELECT * FROM LEVELS";
+    CppSQLite3Query q;
+    QUERYDB(query,q);
 
-       //      std::cout << "** SQL = '"<<query<<"'"<<std::endl;
+    while (!q.eof())
+      {
+       std::string name = q.getStringField(0);
+       GimmickMessage(2," * Importing level '"<<name<<"'"<<std::endl);
+       desc.Add(LevelDescriptor(name));
+       nblevel++;
+       q.nextRow();
+      }   
+    
+    for (int level = 0; level < nblevel; ++level )
+      {
+       std::string table = GetTree().GetLevelDescriptor(level).GetName();
+       table += "_Attributes";
+       // Test table 'LEVELS' existence
+       if ( ! mDB->tableExists(table.c_str()) )
+         {
+           GimmickMessage(1,"!! ERROR : Table '"<<table<<"' does not exist"
+                          <<std::endl);
+           return false;
+         }
        
+       std::string query = "SELECT * FROM ";
+       query += table;
        CppSQLite3Query q;
        QUERYDB(query,q);
        
+       GimmickMessage(2," * Level '"
+                      <<GetTree().GetLevelDescriptor(level).GetName()
+                      <<"'"<<std::endl);
+
+       // Test that ID and PARENT_ID mandatory attributes exist
+       bool ID_found = false;
+       bool PARENT_ID_found = false;
+       if (level==0) ID_found = true;
+       if (level<=1) PARENT_ID_found = true;
 
        while (!q.eof())
          {
-           Field::Description d(q.getStringField(0), // Key
-                                q.getIntField(1), // Group
-                                q.getIntField(2), // Element 
-                                q.getStringField(3), // Name
-                                q.getIntField(4) // Flags
-                                );
-           GetNodeTypeDescription(type).GetFieldDescriptionMap()[d.key] = d;
-           //      std::cout << d << std::endl;
+           std::string key(q.getStringField(0));
+           std::string name(q.getStringField(1));
+           GimmickMessage(2,"  - Importing attribute '"<<key<<"' '"<<name
+                          <<"'"<<std::endl);
+           desc.Add
+             (AttributeDescriptor( key, // Key
+                                   name, // Name
+                                   q.getIntField(2), // Group
+                                   q.getIntField(3), // Element 
+                                   q.getIntField(4) // Flags
+                                   ),level);
+           if ( key == "ID" ) 
+             {
+               ID_found = true;
+             }
+           if ( key == "PARENT_ID" ) 
+             {
+               PARENT_ID_found = true;
+             }
            q.nextRow();
          }
+       
+       if ( ! (ID_found || PARENT_ID_found ) )
+         {
+           GimmickMessage(1,"!! ERROR : Table '"<<table
+                          <<"' does not contain mandatory attribute ID or PARENT_ID"
+                          <<std::endl);
+           return false;
+         }
       }
-    */
-  }
-  //=====================================================================
-
 
-    //=====================================================================
-  bool SQLiteTreeHandler::DBStructureIsValid()
-  {
-    bool success = false; //true;
 
-    // TO DO : TABLE WHICH STORES THE LEVELS
-    /*
-    
-    for (int i = SQLiteTreeHandlerStructure::TableBegin();
-        i    != SQLiteTreeHandlerStructure::TableEnd();++i)
+    // Create the attributes table for Root (i.e. Tree)
+    LevelDescriptor::AttributeDescriptorListType::const_iterator a;
+    for (a = GetTree().GetAttributeDescriptorList(0).begin();
+        a!= GetTree().GetAttributeDescriptorList(0).end();
+        ++a)
       {
-       bool ok = mDB->tableExists(SQLiteTreeHandlerStructure::Table(i));
-       if (ok) 
-         {
-           //      std::cout << "** Table "<<SQLiteTreeHandlerStructure::Table(i)
-           //                <<" exists"<<std::endl;
-           // TO DO : TEST MANDATORY FIELDS EXIST
-         }
-       else 
-         {
-           //      std::cout << "** Table "<<SQLiteTreeHandlerStructure::Table(i)
-           //                <<" does *NOT* exist"<<std::endl;
-           success = false;
-         }
+
+       GetTree().UnsafeSetAttribute( a->GetKey(), "" );
       }
-    */
-    return success;
-  }  
-  //=====================================================================
 
-  /*
-  //=====================================================================
-  int SQLiteTreeHandler::DBLoadChildren(Node* parent, 
-                                       int maxlevel)
-  {
+    // Reading Root attributes
+    // Query DB
+    query = "SELECT * FROM ";
+    query += GetTree().GetLevelDescriptor(0).GetName();
+    QUERYDB(query,q);
 
-    //    std::cout << "SQLiteTreeHandler::DBLoadChildren("<<parent<<","<<maxlevel
-    //       << ")"<<std::endl;
-    int nbloaded = 0;
-    if (parent == GetTree()) { parent = 0; }
-    Node* xparent = parent;
-    if ( xparent==0 ) xparent = GetTree();
-    if ( xparent->ChildrenLoaded() ) 
+    for (int fld = 0; fld < q.numFields(); fld++)
       {
-       //      std::cout << "--> Children already loaded"<<std::endl;
-       return nbloaded;
+       GetTree().UnsafeSetAttribute(q.fieldName(fld),
+                                    q.getStringField(fld));        
       }
-    if ( xparent->GetType() == Node::Image ) 
-      {
-       return nbloaded;
-      }
-    if ( xparent->GetType() >= maxlevel ) 
-      {
-       return nbloaded;
-      }
-   
-    //    msw[2].Pause();
-    //    msw[2].Resume();
-
-    Node::Type type = xparent->GetType()+1;
 
-    // Query DB
-
-    std::string query = "SELECT * FROM ";
-    query += GetTree().GetDescriptor().GetLevelDescriptor(level).GetName();
-      //SQLiteTreeHandlerStructure::Table(type);
-    if (parent!=0)
-      {
-       query += " WHERE PARENT_ID='" + parent->GetFieldValue("ID") + "'";
-      }
-
-    //    std::cout << "** SQL = '"<<query<<"'"<<std::endl;
-
-    CppSQLite3Query q;
-    QUERYDB(query,q);
+    GimmickMessage(1,"Importing tree description from database ... OK"
+                  <<std::endl);
+    return true;
+  }
+  //=====================================================================
 
-    while (!q.eof())
+  //========================================================================
+  /// 
+  std::string& SQLformat(std::string& str)
+  {
+    // quote must be doubled
+    boost::algorithm::replace_all(str,"'","''");
+    // Found strange strings which contained NULL char INSIDE string 
+    int i,size=str.size();
+    for (i=0;i<size;++i) 
       {
-       nbloaded++;
-       Node* n = new Node(type,
-                          this,xparent);
-       for (int fld = 0; fld < q.numFields(); fld++)
-         {
-           n->SetFieldValue(q.fieldName(fld),q.getStringField(fld));       
-         }
-       // Index 
-       TypeId ti;
-       ti.type = type;
-       ti.id = n->GetFieldValue("ID");    
-       mTypeIdToNodeMap[ti] = n;
-       // recurse 
-       if ( type < maxlevel ) 
+       if (str[i]==0) 
          {
-           msw[2].Pause();
-           nbloaded += DBLoadChildren(n,maxlevel);
-           msw[2].Resume();
+           str = str.substr(0,i);
+           break;
          }
-       // next entry in db
-       q.nextRow();
       }
-
-    xparent->SetChildrenLoaded(true);
-    
-    //    msw[2].Pause();
-    return nbloaded;
+    //    if (i<str.size())
+    return str;
   }
+  //========================================================================
+  
   //=====================================================================
+  void SQLiteTreeHandler::SQLAppendAttributesValues(tree::Node* n, 
+                                                   std::string& str)
+  {
+    GimmickMessage(4,"SQLAppendAttributesValues"<<std::endl);
+    std::string atts="";
+    std::string values="";
+    tree::Node::AttributeMapType::iterator i;
+    for (i =  n->GetAttributeMap().begin();
+        i != n->GetAttributeMap().end();
+        i++)
+      {
+       if (i->first=="ID") 
+         {
+           continue;
+         }
 
+       atts += "'" + i->first + "'";
+       values += "'" + SQLformat(i->second) + "'"; 
+       atts += ",";
+       values += ",";
+       GimmickMessage(4,"'"<<i->first<<"' = '"<<i->second<<"'"<<std::endl);
+      }
+    atts[atts.size()-1]=' ';
+    values[values.size()-1]=' ';
 
-
-
-
-
-  //=====================================================================
-  bool SQLiteTreeHandler::DBInsert(Node* alien_node,
-                                  UpdateSummary& summary)
-  {
-    //    std::cout << "SQLiteTreeHandler::Insert('"<<alien_node->GetLabel()
-    //       <<"')"<<std::endl;
-    
-    //    if (!ChildrenLoaded()) DBLoadChildren(this,Node::Database);
-    
-    // Find parent
-    Node* parent;
-    std::string parent_id; 
-    parent = DBGetOrCreateParent(alien_node,parent_id,summary);
-    
-    // Insert 
-    DBRecursiveGetOrCreateNode(alien_node,parent,parent_id,summary);
-   return true;
+    str = "("+atts+") VALUES ("+values+")";
+    GimmickMessage(4,"Result = '"<<str<<"'"<<std::endl);
   }
   //=====================================================================
 
-
   //=====================================================================
-  Node* SQLiteTreeHandler::DBGetOrCreateParent(Node* alien_node,
-                                               std::string& parent_id,
-                                               UpdateSummary& summary)
+  tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr) 
   {
-    //    std::cout << "DBGetOrCreateParent '" << alien_node->GetLabel()<<"'"
-    //       << std::endl;
-    // Load the patients if not already done
-    DBLoadChildren(this,Node::Patient);
-
-    parent_id = "";
-    Node* parent = this;
-
-    // The chain of ancestors
-    std::deque<Node*> chain;
-    Node* cur = alien_node->GetParent();
-    for (int type=Node::Patient; 
-        type<alien_node->GetType();++type)
-      {
-       chain.push_front(cur);
-       cur = cur->GetParent();
-      }
-
-    // create the nodes if do not exist
-    std::deque<Node*>::iterator i;
-    for (i=chain.begin();i!=chain.end();++i)
-      {
-       //      std::cout << " cur = '"<<(*i)->GetLabel()<<"'"<<std::endl;
-       //      std::string cur_id = DBGetNodeId(*i,parent_id);
-       //      if (cur_id.size()==0)
-       //        {
-       // Node does not exist : create it
-       std::string cur_id;
-       parent = DBGetOrCreateNode(*i, 
-                                       parent,
-                                       parent_id,
-                                       cur_id,
-                                       summary
-                                       );
-       DBLoadChildren(parent,parent->GetType()+1);
-
-       parent_id = cur_id;
+    Node* parent = GetTree().GetTree();
+    bool go_down;
+    do 
+      {
+       go_down = false;
+       // Load the children of the current parent
+       DBLoadChildren(parent);
+       // Iterate the children 
+       tree::Node::ChildrenListType::const_iterator i;
+       for (i = parent->GetChildrenList().begin();
+            i!= parent->GetChildrenList().end();
+            ++i)
+         {
+           if ( (*i)->Matches( attr ) ) 
+             {
+               go_down = true;
+               parent = *i;
+               break;
+             }
+         }     
       }
+    while (go_down);
     return parent;
   }
   //=====================================================================
 
-
-
   //=====================================================================
-  void SQLiteTreeHandler::DBRecursiveGetOrCreateNode(Node* alien_node, 
-                                                     Node* parent, 
-                                                     const std::string& parent_id,
-                                                     UpdateSummary& summary)
+  int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, 
+                                       int numberoflevels)
   {
-    //    std::cout << "SQLiteTreeHandler::RecursiveGetOrCreateNode('"
-    //       <<alien_node->GetLabel()
-    //       <<"','"<<parent<<"','"<<parent_id<<"')"<<std::endl;
-    if (parent != 0) 
-      {
-       //      std::cout << " -- Parent = '"<<parent->GetLabel()<<"'"<<std::endl;
-      }   
-    std::string new_id;
-    Node* new_node = DBGetOrCreateNode(alien_node, 
-                                                parent,
-                                                parent_id,
-                                                new_id,
-                                                summary);
-    Node::ChildrenListType::iterator i;
-    for (i  = alien_node->GetChildrenList().begin();
-        i != alien_node->GetChildrenList().end();
-        i++)
-      {
-       DBRecursiveGetOrCreateNode((*i),new_node,new_id,summary);
-      }
-  }
-  //=====================================================================
+    if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) 
+      return 0;
 
+    GimmickMessage(2,"Loading children of '"<<node->GetLabel()
+                  <<"'"<<std::endl);
 
-  //=====================================================================
-  Node* SQLiteTreeHandler::DBGetOrCreateNode(Node* alien_node, 
-                                                  Node* internal_parent,
-                                                  std::string parent_id,
-                                                  std::string& node_id,
-                                                  UpdateSummary& summary)
-  {
-    //   std::cout << "DBGetOrCreateNode('"<<alien_node->GetLabel()<<"','"
-    //       << internal_parent << "','"<< parent_id<<"')"<<std::endl;
-    if (internal_parent != 0) 
+    int nbloaded = 0;
+    // If children loaded we do not have to do it but we need to recurse
+    // in order to load the children's children if necessary, and so on...
+    if (node->GetChildrenLoaded()) 
       {
-       //      std::cout << " -- Parent = '"<<internal_parent->GetLabel()<<"'"<<std::endl;
+       // Iterate the children 
+
+       tree::Node::ChildrenListType::iterator i;
+       for (i = node->GetChildrenList().begin();
+            i!= node->GetChildrenList().end();
+            ++i)
+         {
+           nbloaded += DBLoadChildren(*i,numberoflevels-1);
+         }
+       node->SetChildrenLoaded(true);
+       return nbloaded;
+
       }
-    // Node Exists ? return it 
-    // First try among children of internal parent 
-    Node* node = GetChildrenLike(internal_parent,alien_node);
-    if (node>0)
+       else
+       {
+    /// If children not loaded : do it and recurse
+
+    // Query DB
+    int level = node->GetLevel();
+    std::string query = "SELECT * FROM ";
+       
+    query += GetTree().GetLevelDescriptor(level+1).GetName();
+    if (level>0)
       {
-       node_id = node->UnsafeGetFieldValue("ID");
-       return node;
+       query += " WHERE PARENT_ID='" + node->GetAttribute("ID") 
+         + "'";
       }
-    // Second : try in DB 
-   
-    // Does not exist : Create new one
-    node = new Node(alien_node->GetType(),this,internal_parent);
-    node->SetChildrenLoaded(true);
-    // Copy fields values from alien
-    Node::FieldValueMapType::iterator i,j;
-    for (i =  node->GetFieldValueMap().begin();
-        i != node->GetFieldValueMap().end();
-        i++)
+GimmickDebugMessage(1,                                 "query : '"                         <<query                                         <<std::endl);
+    CppSQLite3Query q;
+    QUERYDB(query,q);
+
+       int p=0;
+    while (!q.eof())
       {
-       j = alien_node->GetFieldValueMap().find(i->first);
-       if (j != alien_node->GetFieldValueMap().end() )
+
+       //      std::cout << "DBLoadCh : creating node level "<<level+1<<std::endl;
+
+       nbloaded++;
+       Node* n = new Node(node);
+       for (int fld = 0; fld < q.numFields(); fld++)
+         {
+           n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));          
+         }
+
+       // recurse 
+       if ( numberoflevels != 1 ) 
          {
-           i->second = j->second;
+           //  msw[2].Pause();
+           nbloaded += DBLoadChildren(n, numberoflevels-1);
+           //      msw[2].Resume();
          }
+       // next entry in db
+       q.nextRow();
       }
 
-    msw[2].Resume();
-    if (node->GetType()!=Node::Patient) 
-      node->SetFieldValue("PARENT_ID",parent_id);
+    node->SetChildrenLoaded(true);
+       
+    
+    //    msw[2].Pause();
+    return nbloaded;
+       }
+  }
+  //=====================================================================
 
-    // Insert in DB
+  //======================================================================
+  void SQLiteTreeHandler::DBInsert(tree::Node* n)
+  {
+    GimmickMessage(2,"Inserting in DB '"<<n->GetLabel()
+                  <<"'"<<std::endl);
     std::string val;
-    BuildSQLFieldsValues(node,val);
+    SQLAppendAttributesValues(n,val);
     std::string insert("INSERT INTO ");
-    insert += std::string(SQLiteTreeHandlerStructure::Table(node->GetType())) 
-      + " " + val + ";";
-    //    std::cout << "** SQL = '"<<insert<<"'"<<std::endl;
-    UPDATEDB(insert);
-    //    std::cout << "** SQL OK"<<std::endl;
+    insert += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
+    insert += " " + val + ";";
 
+    UPDATEDB(insert);
+       
     // Store DB id of newly created node;
     long lastrow = mDB->lastRowId();
     std::stringstream ri;
     ri << mDB->lastRowId();
-    node_id = ri.str();
-    //    std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
-
-    node->SetFieldValue("ID",node_id);
-    // Insert in TypeId map
-    TypeId ti;
-    ti.type = node->GetType();
-    ti.id = node_id;
-    mTypeIdToNodeMap[ti] = node;
-    //    std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl; 
-    // 
-    msw[2].Pause();
-
-    if (node->GetType()==Node::Patient) summary.added_patients++;
-    if (node->GetType()==Node::Study) summary.added_studies++;
-    if (node->GetType()==Node::Series) summary.added_series++;
-    if (node->GetType()==Node::Image) summary.added_images++;
-
-    return node;
+    n->SetAttribute("ID",ri.str());
   }
-  //=====================================================================
+  //======================================================================
 
-  //=====================================================================
-  Node* SQLiteTreeHandler::GetChildrenLike(Node* parent,
-                                           Node* alien_node)
+  //======================================================================
+  /// Graft the branch defined by the attributes to the parent
+  void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, 
+                                           const AttributeMapType& attr)
   {
-    Node::ChildrenListType::iterator i;
-    for (i  = parent->GetChildrenList().begin();
-        i != parent->GetChildrenList().end();
-        i++)
+    //    std::cout <<"Grafting to parent '"<<parent->GetLabel()
+    //            <<"'"<<std::endl;
+
+    for (int level = parent->GetLevel()+1;
+        level < GetTree().GetNumberOfLevels();
+        level++)
       {
-       Node::Type type = alien_node->GetType();
-       bool ok = true;
-       for (int j=0;
-            j<SQLiteTreeHandlerStructure::NbQueryFields(type);
-            j++) 
+       // Create Node
+       tree::Node* child = new tree::Node(parent,attr);
+       child->SetChildrenLoaded(true);
+       if (level>1)
          {
-           if ( 
-               alien_node->GetFieldValue(SQLiteTreeHandlerStructure::
-                                   QueryField(type,j).key )   !=
-               (*i)->GetFieldValue(SQLiteTreeHandlerStructure::
-                                   QueryField(type,j).key ) )
-             {
-               ok = false;
-               break;
-             }
+           int nc = GetNumberOfChildren(parent)+1;
+           
+           //  std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
+           std::stringstream out;
+           out << nc;
+           SetAttribute(parent,"NumberOfChildren",out.str());
          }
-       if (ok) 
-         {
-           return (*i);
+
+       // Set PARENT_ID if necessary 
+       if ( parent->GetLevel()>0 )
+         child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
+       
+       // Insert in DB
+       DBInsert(child);
+       
+       // Down one level
+       parent = child;
          }
-      }
-    return 0;    
   }
-  //=====================================================================
+  //======================================================================
 
-  //=====================================================================
-  std::string SQLiteTreeHandler::DBGetNodeId(Node* node, 
-                                             const std::string& parent_id)
+
+  //===================================================================== 
+  /// Sets an attribute of a Node
+  bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, 
+                                        const std::string& key,
+                                        const std::string& value)
   {
-    //    std::cout << "SQLiteTreeHandler::DBGetNodeId('"<<node->GetLabel()
-    //       <<"','"<<parent_id<<"')"
-    //       <<std::endl;
-    msw[2].Resume();
-    int type = node->GetType();
-
-    std::string table = SQLiteTreeHandlerStructure::Table(type);
-    std::string where = "WHERE ";
-    
-    if (type!=Node::Patient)
-      {
-       where += "PARENT_ID='" + parent_id 
-         //node->GetFieldValue("PARENT_ID") 
-         + "' AND ";
-      }
+    GimmickMessage(3,"Setting Attribute of '"<<n->GetLabel()<<
+                  "' "<<key<<"='"<<value<<"'"<<std::endl);
+
+    n->SetAttribute(key,value);
+    std::string sql = "UPDATE ";
+    sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName();
+    sql += " SET ";
+    sql += key;
+    sql += " = '";
+    sql += value;
+    sql += "' WHERE ID = '";
+    sql += n->GetAttribute("ID");
+       sql +="'";
+    //    sql += " LIMIT 1";
+    UPDATEDB(sql);
+       return true;
+  }
 
-    for (int i=0;i<SQLiteTreeHandlerStructure::NbQueryFields(type);i++) 
-      {
-       where += SQLiteTreeHandlerStructure::QueryField(type,i).key + "='"
-         + node->GetFieldValue(SQLiteTreeHandlerStructure::QueryField(type,i).key) + "' ";
-       if (i<SQLiteTreeHandlerStructure::NbQueryFields(type)-1)
-         where += "AND ";
-    }
+  //===================================================================== 
+  /// Sets an attribute of a Node
+  void SQLiteTreeHandler::DBSetAttribute(const std::string& levelDescriptor, 
+                             const std::string& key,
+                             const std::string& value,
+                                 const std::string& searchParam, 
+                                 const std::string& searchVal)
+  {
 
-    std::string query = "SELECT ID FROM " + table + " " + where + ";";                                                   
-    //    std::cout << "** SQL = '"<<query<<"'"<<std::endl;
-    CppSQLite3Query q;
-    QUERYDB(query,q);
+    std::string sql = "UPDATE ";
+    sql += levelDescriptor;
+    sql += " SET ";
+    sql += key;
+    sql += " = '";
+    sql += value;
+    sql += "' WHERE ";
+       sql += searchParam;
+       sql += " = '";
+    sql += searchVal;
+       sql += "'";
+       std::cout<<sql<<std::endl;
+    UPDATEDB(sql);
+  }
+   //=====================================================================
+  void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
+  {
+       
+    std::string query = "DELETE FROM ";
+   
 
-    if (!q.eof())
-      {
+       query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
        
-       //      std::cout << " - Node exists " << std::endl;
-       std::string id = q.getStringField(0);
-       //      std::cout << " id = '"<<id<<"'"<<std::endl;
-       msw[2].Pause();
-       return id;
-      }
-    msw[2].Pause();
-    return "";
+    query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
+    UPDATEDB(query);
+       GimmickDebugMessage(2,
+                           " Deleting '"
+                               <<node->GetLabel()<<"' with ID '"
+                           <<node->GetAttribute("ID")
+                           <<"' in level "<< GetTree().GetLevelDescriptor(node->GetLevel()).GetName()
+                           <<std::endl);
+
+
+       if(node->GetNumberOfChildren()!=0)
+       {
+               Node::ChildrenListType::iterator i;
+               for (i  = node->GetChildrenList().begin();
+               i != node->GetChildrenList().end();
+               i++)
+               {
+               DBRecursiveRemoveNode((*i));
+               }
+       }
+       else if(node->GetLevel()<GetTree().GetNumberOfLevels()-1)
+       {
+               DBRecursiveRemoveNode(node->GetLevel()+1,node->GetAttribute("ID"));
+    }
   }
-  //=====================================================================
-
-
 
   //=====================================================================
-  Node* SQLiteTreeHandler::GetNodeFromTypeId(Node::Type type,
-                                      const std::string& id)
+  void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId)
   {
-    //    std::cout << "GetNodeFromTypeId("<<type<<","<<id<<")"<<std::endl;
-
-    TypeId ti;
-    ti.type = type;
-    ti.id = id;
+    std::stringstream out;
+       std::stringstream result;
+       out<<"SELECT ID FROM "<<GetTree().GetLevelDescriptor(level).GetName()<<" WHERE PARENT_ID='"<<parentId<<"'";
+               
+       CppSQLite3Query q;
+       QUERYDB(out.str(),q);
+       
+       while (!q.eof())
+         {
+           for (int fld = 0; fld < q.numFields(); fld++)
+             {
+                         result<<q.getStringField(fld)<<"#";
+             }
+           q.nextRow();
+         }
+         std::string res=result.str();
+         size_t ini=0;
+         size_t fin=0;
+         while(fin<res.size()-1)
+         {
+          fin=res.find('#',ini);
+          DBDelete(GetTree().GetLevelDescriptor(level).GetName(),"ID",res.substr(ini,fin-ini));
+         if(level<GetTree().GetNumberOfLevels()-1)
+         {
+               DBRecursiveRemoveNode(level+1,res.substr(ini,fin-ini));
+         } 
+          ini=fin+1;
+         }
+         
     
-    TypeIdToNodeMapType::iterator i = mTypeIdToNodeMap.find(ti);
-    if (i == mTypeIdToNodeMap.end())
-      {
-
-           std::cout << "Internal error : mTypeIdToNodeMap does not contain key"
-                     << std::endl;
-           creaError("Internal error : mTypeIdToNodeMap does not contain key");
-           // }
-      }
-
-    //    std::cout << " ** Node = "<<i->second<<std::endl;
-    return i->second;
   }
-  //=====================================================================
 
   //=====================================================================
-  bool SQLiteTreeHandler::Remove(Node* node)
+  void SQLiteTreeHandler::DBDelete(std::string levelDescriptor, std::string key, std::string value)
   {
-    DBRecursiveRemoveNode(node);
+       
+    std::stringstream query;
+       query<<"DELETE FROM "<<levelDescriptor<<" WHERE "<<key<<"='"<<value<<"';";
  
-    //    std::cout << "DELETE"<<std::endl;
-    if (node->GetParent())
-      {
-       node->GetParent()->RemoveChildrenFromList(node);
-      }
-    delete node;
-    //    std::cout << "DELETE OK"<<std::endl;
-    return true;
+    UPDATEDB(query.str());
+       GimmickDebugMessage(2," Deleting: Query: "<<query.str()<<std::endl);
   }
-  //========================================================================
 
-  //=====================================================================
-  void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
-  {
-    //    std::cout << "SQLiteTreeHandler::DBRecursiveRemoveNode('"
-    //       <<node->GetLabel()<<"')"<<std::endl;
-
-    std::string query = "DELETE FROM ";
-    query += SQLiteTreeHandlerStructure::Table(node->GetType());
-    query += " WHERE ID='"+ node->GetFieldValue("ID") + "';";
-    UPDATEDB(query);
 
-    Node::ChildrenListType::iterator i;
-    for (i  = node->GetChildrenList().begin();
-        i != node->GetChildrenList().end();
-        i++)
-      {
-       DBRecursiveRemoveNode((*i));
-      }
+  //===================================================================== 
+  void SQLiteTreeHandler::GetAttribute(std::string levelDescriptor,
+                                                                          std::string searchParam, 
+                                                                          std::string searchVal, 
+                                                                          std::string key, 
+                                                                          std::string& result) 
+  { 
+       std::stringstream out;
+       std::stringstream results;
+       out<<"SELECT "<<key<<" FROM "<<levelDescriptor;
+       if(searchParam!="")
+       {
+               out<<" WHERE "<<searchParam<<"='"<<searchVal<<"'";
+       }
+       
+       CppSQLite3Query q;
+       QUERYDB(out.str(),q);
+       
+       
+       while (!q.eof())
+         {
+           for (int fld = 0; fld < q.numFields(); fld++)
+             {
+                         results<<q.getStringField(fld);
+                         if(searchParam=="")
+                         {
+                                 results<<"#";
+                         }
+             }
+           q.nextRow();
+         }
+       result=results.str();
+      
   }
-  //=====================================================================
-  
-  //=====================================================================
-  int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node)
-  {
-    std::string query = "SELECT COUNT (ID) FROM ";
-    query += SQLiteTreeHandlerStructure::Table(node->GetType()+1);
-    if (node->GetType() != Node::Database) 
-      {
-       query += " WHERE PARENT_ID='"+ node->GetFieldValue("ID")+"'";
-      }
-    query  += ";";
-    
-    //   std::cout << "**SQL = "<< query << std::endl;
-    
-    CppSQLite3Query q;
-    QUERYDB(query,q);
-   
-     //    std::cout << "**RES = "<< q.getIntField(0) <<std::endl;
+  //===================================================================== 
+  unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
+  { 
+    // Query DB
+    int nb=0;
+    int level = n->GetLevel();
 
-    return q.getIntField(0);
-  }
-  //=====================================================================
-  //========================================================================
-  std::string& format_sql2(std::string& str)
-  {
-    // quote must be doubled
-    //    crea::Utils::Replace( str, "'", "''" );
-    boost::algorithm::replace_all(str,"'","''");
-    // Found strange strings which contained NULL char INSIDE string 
-    int i,size=str.size();
-    for (i=0;i<size;++i) 
+    if(level<GetTree().GetNumberOfLevels()&& level>0)
       {
-       if (str[i]==0) 
+       std::string query = "SELECT NumberOfChildren FROM ";
+       query += GetTree().GetLevelDescriptor(level).GetName();
+       if (level>0)
          {
-           str = str.substr(0,i);
-           break;
+           query += " WHERE ID='" + n->GetAttribute("ID") 
+             + "'";
+         }
+       CppSQLite3Query q;
+       QUERYDB(query,q);
+       
+       
+       while (!q.eof())
+         {
+           for (int fld = 0; fld < q.numFields(); fld++)
+             {
+               nb=q.getIntField(fld);  
+             }
+           q.nextRow();
          }
       }
-    //    if (i<str.size())
-    return str;
+    /*
+    if(nb==0)
+      { 
+       nb=1;
+      }
+    */
+    return nb; 
   }
-   //========================================================================
 
-  //=====================================================================
-  void SQLiteTreeHandler::BuildSQLFieldsValues(Node* n,
-                                       std::string& str)
+  //===================================================================== 
+  void SQLiteTreeHandler::GetTopLevelNodeId(const std::string& searchParam, const std::string& searchValue, std::string& parent_id) 
   {
-    //    std::cout << "BuildSQLFieldsValues('"<<n->GetLabel()<<"')"<<std::endl;
+         int level=GetTree().GetNumberOfLevels()-1;
+         std::string sp=searchParam.c_str();
+         std::string sv=searchValue.c_str();
 
-    std::string atts="";
-    std::string values="";
-    Node::FieldValueMapType::iterator i;
-    for (i =  n->GetFieldValueMap().begin();
-        i != n->GetFieldValueMap().end();
-        i++)
-      {
-       if (i->first=="ID") 
+         while(level>1)
          {
-           continue;
+               std::stringstream out;
+               std::stringstream results;
+               out<<"SELECT PARENT_ID FROM "<<GetTree().GetLevelDescriptor(level).GetName();
+               out<<" WHERE "<<sp<<"='"<<sv<<"'";      
+               CppSQLite3Query q;
+               QUERYDB(out.str(),q);
+               
+               
+               while (!q.eof())
+               {
+                       for (int fld = 0; fld < q.numFields(); fld++)
+                       {
+                               results<<q.getStringField(fld);
+                       }
+                       q.nextRow();
+               }
+               level=level-1;
+               sp="ID";
+               sv=results.str();
          }
-       //      std::cout << "("<<i->first<<","<<i->second<<")"<<std::endl;
-       atts += "'" + i->first + "'";
-       values += "'" + format_sql2(i->second) + "'"; 
-       atts += ",";
-       values += ",";
-      }
-    atts[atts.size()-1]=' ';
-    values[values.size()-1]=' ';
-
-    str = "("+atts+") VALUES ("+values+")";
+         parent_id=sv;
 
   }
-  //=====================================================================
-*/
-
 
+  //=====================================================================
+  void SQLiteTreeHandler::RemoveEntries(const std::string i_table, 
+               const std::string i_attribute, 
+               const std::string i_operand, 
+               const std::string i_val)
+    {
+        std::stringstream query;
+               query<<"DELETE  FROM "<<i_table<<" WHERE "<<i_attribute<<" "<<i_operand<<" '"<<i_val<<"'";
+        UPDATEDB(query.str());
+       }
+
+       //=====================================================================
+  void SQLiteTreeHandler::BeginTransaction()
+    {
+               std::stringstream out;
+               out<<"begin transaction;";
+        UPDATEDB(out.str());
+       }
+
+       //=====================================================================
+  void SQLiteTreeHandler::EndTransaction()
+    {
+       std::stringstream out;
+               out<<"commit transaction;";
+        UPDATEDB(out.str());
+       }
 
 } // namespace creaImageIO