#include <deque>
-#include "wx/wx.h"
-#include <wx/dir.h>
-#include <wx/filename.h>
-
-
//#include <icons/close.xpm>
#include <creaWx.h>
-#include <creaMessageManager.h>
using namespace crea;
#include <boost/filesystem.hpp>
: mFileName(filename)
{
mDB = new CppSQLite3DB;
+ mIsAdding=false;
GimmickMessage(1,"SQLite version : "
<<std::string(mDB->SQLiteVersion())<< std::endl);
}
//=============================================================
- //=============================================================
- 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 \
- { \
- GimmickMessage(2,"SQL: '"<<QUER<<"'"<<std::endl); \
- 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 \
- { \
- GimmickMessage(2,"SQL: '"<<UP<<"'"<<std::endl); \
- 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)
//=====================================================================
bool SQLiteTreeHandler::Close()
{
- return false;
+ return true;
}
//=====================================================================
{
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);
}
//=====================================================================
}
//=====================================================================
-
//=====================================================================
- 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);
+ }
+ //=====================================================================
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //=====================================================================
+ // 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()
{
- GimmickMessage(2,"Opening SQLite database '"<<GetFileName()<<std::endl);
+ GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
+ <<"' ... "<<std::endl);
// OPENING FILE
if (!boost::filesystem::exists(GetFileName()))
{
}
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;
}
//=====================================================================
//=====================================================================
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;
}
}
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;
- // Create LEVELS table
- command = "create table LEVELS\n";
- command += "( Name text )\n";
- UPDATEDB(command);
-
- // Level 0
- command = "INSERT INTO Levels (Name) VALUES ('";
- command += GetTree().GetLevelDescriptor(0).GetName();
+
+ 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);
-
- command = "CREATE TABLE ";
- command += GetTree().GetLevelDescriptor(0).GetName();
- command += "\n(\nID INTEGER PRIMARY KEY";
- AppendAttributesSQLDefinition(0,command);
- command += "\n)";
- UPDATEDB(command);
- // Iterate the other Levels
- for (int l=1; l<GetTree().GetNumberOfLevels(); ++l)
+ // Create table of level (for level>0, i.e. not Root)
+ if (l>=0)
{
- command = "INSERT INTO LEVELS (Name) VALUES ('";
- command += GetTree().GetLevelDescriptor(l).GetName();
- command += "')";
- UPDATEDB(command);
-
command = "CREATE TABLE ";
command += GetTree().GetLevelDescriptor(l).GetName();
- command += "\n(\nID INTEGER PRIMARY KEY,\nPARENT_ID int not null";
- AppendAttributesSQLDefinition(l,command);
- command +=",\n";
- command +="constraint FK_PARENT foreign key (PARENT_ID) references PATIENT(ID) on delete restrict on update restrict\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);
+ }
+
}
- // Create tables *_ATTRIBUTES
- // and 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;
- }
- }
- //=====================================================================
-
- //=====================================================================
- void SQLiteTreeHandler::AppendAttributesSQLDefinition(int level,
- std::string& s)
- {
- LevelDescriptor::AttributeDescriptorListType::const_iterator i;
- for (i = GetTree().GetAttributeDescriptorList(level).begin();
- i != GetTree().GetAttributeDescriptorList(level).end();
- ++i)
- {
- // if (i->second.flags==1) continue;
- s += ",\n";
- s += i->GetKey();
- s += " text";
- }
- }
- //=====================================================================
-
- //=====================================================================
- void SQLiteTreeHandler::DBExportTreeDescription()
- {
- for (int level=0; level<GetTree().GetNumberOfLevels(); ++level)
- {
- std::string command;
command = "CREATE TABLE ";
- command += GetTree().GetLevelDescriptor(level).GetName();
+ command += GetTree().GetLevelDescriptor(l).GetName();
command += "_Attributes\n(\n";
command += "Key text,\n";
command += "Name text,\n";
command += "Flags int\n";
command += "\n)";
UPDATEDB(command);
-
+
+
+ // Fill the table *_ATTRIBUTES
LevelDescriptor::AttributeDescriptorListType::const_iterator i;
- for (i = GetTree().GetAttributeDescriptorList(level).begin();
- i != GetTree().GetAttributeDescriptorList(level).end();
+ for (i = GetTree().GetAttributeDescriptorList(l).begin();
+ i != GetTree().GetAttributeDescriptorList(l).end();
++i)
{
std::stringstream insert;
insert << "INSERT INTO "
- << GetTree().GetLevelDescriptor(level).GetName()
+ << GetTree().GetLevelDescriptor(l).GetName()
<< "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
<< "VALUES ('"
<< i->GetKey() << "','"
<< 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::DBImportTreeDescription()
+ void SQLiteTreeHandler::SQLAppendAttributesDefinition(int level,
+ std::string& s)
{
- GimmickMessage(3,"ImportTreeDescription"<<std::endl);
-
- // tree::Description& desc = GetTree().GetDescription();
- /*
+ LevelDescriptor::AttributeDescriptorListType::const_iterator i;
+ for (i = GetTree().GetAttributeDescriptorList(level).begin();
+ i != GetTree().GetAttributeDescriptorList(level).end();
+ ++i)
+ {
+ // if (i->second.flags==1) continue;
+ s += ",\n";
+ s += i->GetKey();
+ s += " text";
+ }
+ }
+ //=====================================================================
+
+
+ //=====================================================================
+ bool SQLiteTreeHandler::DBImportTreeDescription()
+ {
+ GimmickMessage(1,"Importing tree description for database ..."
+ <<std::endl);
- for (Node::Type type=Node::Patient;
- type<=Node::Image;
- type++)
+ // 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 = 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++)
+ 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++)
{
- i->second = j->second;
+ n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));
}
+
+ // recurse
+ if ( numberoflevels != 1 )
+ {
+ // 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++)
- {
- if (
- alien_node->GetFieldValue(SQLiteTreeHandlerStructure::
- QueryField(type,j).key ) !=
- (*i)->GetFieldValue(SQLiteTreeHandlerStructure::
- QueryField(type,j).key ) )
- {
- ok = false;
- break;
- }
- }
- if (ok)
+ // Create Node
+ tree::Node* child = new tree::Node(parent,attr);
+ child->SetChildrenLoaded(true);
+ if (level>1)
{
- return (*i);
+ int nc = GetNumberOfChildren(parent)+1;
+
+ // std::cout<<"Number of children "<<parent->GetNumberOfChildren()<<std::endl;
+ std::stringstream out;
+ out << nc;
+ SetAttribute(parent,"NumberOfChildren",out.str());
}
- }
- return 0;
- }
- //=====================================================================
-
- //=====================================================================
- std::string SQLiteTreeHandler::DBGetNodeId(Node* node,
- const std::string& parent_id)
- {
- // 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 ";
- }
- 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 ";
- }
-
- std::string query = "SELECT ID FROM " + table + " " + where + ";";
- // std::cout << "** SQL = '"<<query<<"'"<<std::endl;
- CppSQLite3Query q;
- QUERYDB(query,q);
-
- if (!q.eof())
- {
+ // Set PARENT_ID if necessary
+ if ( parent->GetLevel()>0 )
+ child->SetAttribute("PARENT_ID",parent->GetAttribute("ID"));
- // 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 "";
+ // Insert in DB
+ DBInsert(child);
+
+ // Down one level
+ parent = child;
+ }
}
- //=====================================================================
+ //======================================================================
-
- //=====================================================================
- Node* SQLiteTreeHandler::GetNodeFromTypeId(Node::Type type,
- const std::string& id)
+ //=====================================================================
+ /// Sets an attribute of a Node
+ bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n,
+ const std::string& key,
+ const std::string& value)
{
- // std::cout << "GetNodeFromTypeId("<<type<<","<<id<<")"<<std::endl;
-
- TypeId ti;
- ti.type = type;
- ti.id = id;
-
- 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;
+ 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;
}
- //=====================================================================
- //=====================================================================
- bool SQLiteTreeHandler::Remove(Node* node)
+ //=====================================================================
+ /// 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)
{
- DBRecursiveRemoveNode(node);
-
- // std::cout << "DELETE"<<std::endl;
- if (node->GetParent())
- {
- node->GetParent()->RemoveChildrenFromList(node);
- }
- delete node;
- // std::cout << "DELETE OK"<<std::endl;
- return true;
- }
- //========================================================================
- //=====================================================================
+ 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::cout << "SQLiteTreeHandler::DBRecursiveRemoveNode('"
- // <<node->GetLabel()<<"')"<<std::endl;
-
+
std::string query = "DELETE FROM ";
- query += SQLiteTreeHandlerStructure::Table(node->GetType());
- query += " WHERE ID='"+ node->GetFieldValue("ID") + "';";
+
+ query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName();
+ query += " WHERE ID='"+ node->GetAttribute("ID") + "';";
UPDATEDB(query);
-
- Node::ChildrenListType::iterator i;
- for (i = node->GetChildrenList().begin();
- i != node->GetChildrenList().end();
- i++)
- {
- DBRecursiveRemoveNode((*i));
- }
+ 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"));
+ }
}
+
//=====================================================================
-
- //=====================================================================
- int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node)
+ void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId)
{
- 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;
+ 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;
+ }
+
- CppSQLite3Query q;
- QUERYDB(query,q);
-
- // std::cout << "**RES = "<< q.getIntField(0) <<std::endl;
-
- return q.getIntField(0);
}
+
//=====================================================================
-
- //========================================================================
- std::string& format_sql2(std::string& str)
+ void SQLiteTreeHandler::DBDelete(std::string levelDescriptor, std::string key, std::string value)
{
- // 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)
+
+ std::stringstream query;
+ query<<"DELETE FROM "<<levelDescriptor<<" WHERE "<<key<<"='"<<value<<"';";
+
+ UPDATEDB(query.str());
+ GimmickDebugMessage(2," Deleting: Query: "<<query.str()<<std::endl);
+ }
+
+
+ //=====================================================================
+ 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();
+
+ }
+ //=====================================================================
+ unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n)
+ {
+ // Query DB
+ int nb=0;
+ int level = n->GetLevel();
+
+ 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