#include <creaImageIOGimmick.h>
#include <creaImageIOSystem.h>
-#include <creaImageIOImageFinder.h>
-
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
+#ifndef PATH_MAX // If not defined yet : do it
+# define PATH_MAX 2048
+#endif
+
namespace creaImageIO
{
-
+
+
//==============================================================
Gimmick::Gimmick()
+ : mImageAdder(0)
{
- crea::MessageManager::RegisterMessageType("Gimmick!",
- "Gimmick",1);
- crea::MessageManager::RegisterMessageType("Gimmick! DEBUG",
- "Gimmick",0);
+ RegisterGimmickMessageTypes();
+ mSettings=0;
+ mSynchronizer=0;
}
//==============================================================
//==============================================================
Gimmick::~Gimmick()
{
-
+ if(mSettings!=0)
+ {
+ mSettings->writeSettingsFile();
+ delete mSettings;
+ }
+ if(mSynchronizer!=0)
+ {
+ delete mSynchronizer;
+ }
}
//==============================================================
//==============================================================
void Gimmick::Initialize()
{
+ std::string i_nameDB = "Local database";
// Create the UserSettings dir if does not exist
CreateUserSettingsDirectory();
// Sets the current directory to the home dir
mCurrentDirectory = GetHomeDirectory();
+ mSynchronizer= new Synchronizer(GetUserSettingsDirectory());
+
+ mSettings = new Settings(mCurrentDirectory);
+
+
+ std::string dbpath = GetLocalDatabasePath();
+ // Create or open local database
+ mLocalDatabase = createDB(i_nameDB, mCurrentDirectory + "\\.gimmick\\localdatabase_Descriptor.txt", dbpath);
+ // Add it to the TreeHandlerMap
+ mTreeHandlerMap[i_nameDB] = mLocalDatabase;
+
+ //Add additional DB from user Settings
+ addDBSettings();
- // Create local database handler
- mLocalDatabase = new SQLiteTreeHandler(GetLocalDatabasePath());
+ // Creates files and directories database
+ mTimestampDatabase = new TimestampDatabaseHandler(GetTimestampDatabasePath());
// Create or open local database
- if (! boost::filesystem::exists( GetLocalDatabasePath() ) )
+ if (! boost::filesystem::exists( GetTimestampDatabasePath() ) )
{
- std::string mess = "Local database '";
- mess += GetLocalDatabasePath();
+ std::string mess = "Timestamp database '";
+ mess += GetTimestampDatabasePath();
mess += "' does not exist : creating it";
GimmickMessage(1,mess<<std::endl);
- // CREATING DEFAULT DB STRUCTURE
- mLocalDatabase->GetTree().GetDescriptor().CreateDefault();
-
- if ( ! mLocalDatabase->Create(true) )
+ if ( ! mTimestampDatabase->Create() )
{
- GimmickError("ERROR CREATING '"<<GetLocalDatabasePath()<<"'");
+ GimmickError("ERROR CREATING '"<<GetTimestampDatabasePath()<<"'");
}
- mLocalDatabase->SetAttribute(0,"Name","Local database");
- }
+
+ }
else
{
/// Open and test it
- GimmickMessage(1,"Opening local database '"
- <<GetLocalDatabasePath()<<"' "
+ GimmickMessage(1,"Opening Timestamp database '"
+ <<GetTimestampDatabasePath()<<"' "
<<std::endl);
- if ( ! mLocalDatabase->Open(true) )
+ if ( ! mTimestampDatabase->Open() )
{
- GimmickError("ERROR OPENING '"<<GetLocalDatabasePath()<<"'");
+ GimmickError("ERROR OPENING '"<<GetTimestampDatabasePath()<<"'");
}
}
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // add DB to TreeHandler Map //
+ // @param i_name : DB name //
+ // @param i_location : DB location //
+ // return : - //
+ ///////////////////////////////////////////////////////////////////////
+ void Gimmick::addDB(const std::string &i_name,
+ const std::string &i_location)
+ {
+ if(mTreeHandlerMap.find(i_name) == mTreeHandlerMap.end())
+ {
+ mTreeHandlerMap[i_name] = new SQLiteTreeHandler(i_location);
+ mTreeHandlerMap[i_name]->Open(true);
+ mSettings->addDB(i_location);
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // create a DB from a attributes descriptor file for medical images //
+ // @param i_name : DB name //
+ // @param i_locDesc : location of descriptor file //
+ // @param i_locDB : location of DB //
+ // return : the SQLiteTreeHandler object on DB //
+ /////////////////////////////////////////////////////////////////////////
+ SQLiteTreeHandler *Gimmick::createDB(const std::string &i_name,
+ const std::string &i_locDesc,
+ const std::string &i_locDB)
+ {
+ SQLiteTreeHandler *sqlTreeH = new SQLiteTreeHandler(i_locDB);
+ // Create or open local database
+ if (! boost::filesystem::exists(i_locDB) )
+ {
+ std::string mess = "Local database '";
+ mess += i_locDB;
+ mess += "' does not exist : creating it";
+ GimmickMessage(1,mess<<std::endl);
+
+ // CREATING DB STRUCTURE
+ sqlTreeH->GetTree().GetDescriptor().createDescriptorfromFile(i_locDesc);
+ if ( ! sqlTreeH->Create(true) )
+ {
+ GimmickError("ERROR CREATING '"<<i_locDB<<"'");
+ }
+ sqlTreeH->SetAttribute(0,"Name",i_name);
+ }
+ else
+ {
+ /// Open and test it
+ GimmickMessage(1,"Opening local database '" <<i_locDB<< "' " << std::endl);
+ if ( !sqlTreeH->Open(true) )
+ {
+ GimmickError("ERROR OPENING '"<<i_locDB<<"'");
+ }
+ }
+ return sqlTreeH;
}
- //================================================================
//==============================================================
void Gimmick::Finalize()
{
- delete mLocalDatabase;
+
+ // delete SQLiteTreeHandler Object
+ for( TreeHandlerMapType::const_iterator it = mTreeHandlerMap.begin();
+ it!= mTreeHandlerMap.end(); ++it)
+ {
+ delete it->second;
+ }
+ delete mTimestampDatabase;
}
//==============================================================
}
//================================================================
+ //================================================================
+ int Gimmick::GetBinaryDirectory(char *pname, size_t pathsize)
+ {
+
+ #ifdef LINUX
+ /* Oddly, the readlink(2) man page says no NULL is appended. */
+ /* So you have to do it yourself, based on the return value: */
+ pathsize --; /* Preserve a space to add the trailing NULL */
+ long result = readlink("/proc/self/exe", pname, pathsize);
+ if (result > 0)
+ {
+ pname[result] = 0; /* add the #@!%ing NULL */
+
+ if ((access(pname, 0) == 0))
+ return 0; /* file exists, return OK */
+ /*else name doesn't seem to exist, return FAIL (falls
+ through) */
+ }
+ #endif /* LINUX */
+
+ #ifdef WIN32
+ long result = GetModuleFileName(NULL, pname, pathsize);
+ if (result > 0)
+ {
+ /* fix up the dir slashes... */
+ int len = strlen(pname);
+ int idx;
+ for (idx = 0; idx < len; idx++)
+ {
+ if (pname[idx] == '\\') pname[idx] = '/';
+ }
+
+ for (idx = len-1; idx >=0 ; idx--)
+ {
+ if (pname[idx] == '/')
+ {
+ pname[idx+1] = '\0';
+ idx = -1;
+ }
+ }
+
+ if ((access(pname, 0) == 0))
+ return 0; /* file exists, return OK */
+ /*else name doesn't seem to exist, return FAIL (falls
+ through) */
+ }
+ #endif /* WIN32 */
+
+ #ifdef SOLARIS
+ char *p = getexecname();
+ if (p)
+ {
+ /* According to the Sun manpages, getexecname will
+ "normally" return an */
+ /* absolute path - BUT might not... AND that IF it is not,
+ pre-pending */
+ /* getcwd() will "usually" be the correct thing... Urgh!
+ */
+
+ /* check pathname is absolute (begins with a / ???) */
+ if (p[0] == '/') /* assume this means we have an
+ absolute path */
+ {
+ strncpy(pname, p, pathsize);
+ if ((access(pname, 0) == 0))
+ return 0; /* file exists, return OK */
+ }
+ else /* if not, prepend getcwd() then check if file
+ exists */
+ {
+ getcwd(pname, pathsize);
+ long result = strlen(pname);
+ strncat(pname, "/", (pathsize - result));
+ result ++;
+ strncat(pname, p, (pathsize - result));
+
+ if ((access(pname, 0) == 0))
+ return 0; /* file exists, return OK */
+ /*else name doesn't seem to exist, return FAIL
+ (falls through) */
+ }
+ }
+ #endif /* SOLARIS */
+
+ #ifdef MACOSX /* assume this is OSX */
+ /*
+ from http://www.hmug.org/man/3/NSModule.html
+
+ extern int _NSGetExecutablePath(char *buf, unsigned long
+ *bufsize);
+
+ _NSGetExecutablePath copies the path of the executable
+ into the buffer and returns 0 if the path was successfully
+ copied in the provided buffer. If the buffer is not large
+ enough, -1 is returned and the expected buffer size is
+ copied in *bufsize. Note that _NSGetExecutablePath will
+ return "a path" to the executable not a "real path" to the
+ executable. That is the path may be a symbolic link and
+ not the real file. And with deep directories the total
+ bufsize needed could be more than MAXPATHLEN.
+ */
+
+ int status = -1;
+ char *given_path = (char*)malloc(MAXPATHLEN * 2);
+ if (!given_path) return status;
+
+ uint32_t npathsize = MAXPATHLEN * 2;
+ long result = _NSGetExecutablePath(given_path, &npathsize);
+ if (result == 0)
+ { /* OK, we got something - now try and resolve the real path...
+ */
+ if (realpath(given_path, pname) != NULL)
+ {
+ if ((access(pname, 0) == 0))
+ status = 0; /* file exists, return OK */
+ }
+ }
+ free (given_path);
+ return status;
+ #endif /* MACOSX */
+
+ return -1; /* Path Lookup Failed */
+ }
+
//================================================================
const std::string& Gimmick::GetLocalDatabasePath()
{
}
return mLocalDatabasePath;
}
+
+ //================================================================
+
+ //================================================================
+ const std::string& Gimmick::GetTimestampDatabasePath()
+ {
+ if (mTimestampDatabasePath.size()==0)
+ {
+ mTimestampDatabasePath = GetUserSettingsDirectory();
+ mTimestampDatabasePath += "timestamp_database.sqlite3";
+ boost::algorithm::replace_all( mTimestampDatabasePath,
+ INVALID_FILE_SEPARATOR ,
+ VALID_FILE_SEPARATOR);
+ }
+ return mTimestampDatabasePath;
+ }
//========================================================================
//========================================================================
GimmickError("ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
}
}
+
+ std::string setDir=GetUserSettingsDirectory();
+ boost::algorithm::replace_all( setDir,
+ VALID_FILE_SEPARATOR ,
+ INVALID_FILE_SEPARATOR);
+ setDir+="localdatabase_Descriptor.txt";
+ if(!boost::filesystem::is_regular_file(setDir))
+ {
+ char name[PATH_MAX];
+ int err = GetBinaryDirectory(name, PATH_MAX);
+ std::string path=name;
+ path=path.substr(0,path.size()-1);
+ path=path.substr(0,path.find_last_of("/"));
+ path+="/data/localdatabase_Descriptor.txt";
+ boost::algorithm::replace_all( path,
+ VALID_FILE_SEPARATOR ,
+ INVALID_FILE_SEPARATOR);
+ boost::filesystem::copy_file(path,setDir);
+ }
}
//========================================================================
/// Sets message level
void Gimmick::SetMessageLevel(int l)
{
- crea::MessageManager::SetMessageLevel("Gimmick!",l);
+ SetGimmickMessageLevel(l);
}
//========================================================================
/// Sets message level
void Gimmick::SetDebugMessageLevel(int l)
{
- crea::MessageManager::SetMessageLevel("Gimmick! DEBUG",l);
+ SetGimmickDebugMessageLevel(l);
}
//========================================================================
//========================================================================
- /// Add a file to the local database
- void Gimmick::AddFileToLocalDatabase(const std::string& f)
- {
- ImageFinder finder(mLocalDatabase);
- if (finder.IsHandledFile(f))
+ /// Returns the tree handler with the given name
+ TreeHandler* Gimmick::GetTreeHandler(const std::string& name) const
+ {
+ TreeHandlerMapType::const_iterator i;
+ i = GetTreeHandlerMap().find(name);
+ if ( i == GetTreeHandlerMap().end() )
{
- finder.AddFile(f);
+ GimmickError("TreeHandler '"<<name<<"' does not exist");
}
- else
- {
- GimmickError("File '"<<f<<"' does not exist or is not handled");
- }
+ return i->second;
+ }
+
+ //========================================================================
+ ///Returns the timestamp database handler
+ TimestampDatabaseHandler* Gimmick::GetTimestampDatabase() const
+ {
+ return mTimestampDatabase;
+ }
+
+
+ //========================================================================
+ /// Add the files to the tree handler
+ void Gimmick::AddFiles(const std::string& d,
+ const std::vector<std::string>& filenames)
+ {
+ GimmickMessage(2,"Adding files to '"<<d<<"'"<<std::endl);
+
+ mImageAdder.SetCurrentDatabase(d);
+ mImageAdder.SetTreeHandler(GetTreeHandler(d));
+ mImageAdder.SetTimestampHandler(mTimestampDatabase);
+ mImageAdder.SetSynchronizer(mSynchronizer);
+ mImageAdder.AddFiles(filenames);
+
}
//========================================================================
//========================================================================
/// Add a dir to the local database
- void Gimmick::AddDirToLocalDatabase(const std::string& f, bool recurse)
+ void Gimmick::AddDir(const std::string& d, const std::string& f,
+ bool recurse)
{
- ImageFinder finder(mLocalDatabase);
-
- finder.AddDirectory(f,recurse);
-
+ GimmickMessage(2,"Adding dir '"<<f<<"' to '"<<d<<"' recurse:"
+ <<recurse<<std::endl);
+
+ TreeHandler * handler=GetTreeHandler(d);
+ mImageAdder.SetCurrentDatabase(d);
+ mImageAdder.SetTreeHandler(handler);
+ mImageAdder.SetTimestampHandler(mTimestampDatabase);
+ mImageAdder.SetSynchronizer(mSynchronizer);
+ mImageAdder.AddDirectory(f,recurse);
+ }
+
+ //========================================================================
+
+ //========================================================================
+ void Gimmick::RemoveFile(const std::string& d,
+ tree::Node* node)
+ {
+ mImageAdder.SetCurrentDatabase(d);
+ mImageAdder.SetSynchronizer(mSynchronizer);
+ mTimestampDatabase->RemoveNode("PATH",node,d);
+ mImageAdder.RemoveFile(node);
+ }
+ //========================================================================
+
+ //========================================================================
+
+ void Gimmick::CopyFiles(const std::vector<std::string>& filenames, const std::string& d )
+ {
+ TreeHandler * handler=GetTreeHandler(d);
+ mImageAdder.SetCurrentDatabase(d);
+ mImageAdder.SetTreeHandler(handler);
+ mImageAdder.SetTimestampHandler(mTimestampDatabase);
+ mImageAdder.SetSynchronizer(mSynchronizer);
+ mImageAdder.CopyFiles(filenames, mSettings->getValue(SETTINGS_COPY_PATH));
}
+
//========================================================================
+
+ std::string Gimmick::Synchronize(const std::string& d, bool repair, bool checkAttributes)
+ {
+ TreeHandler * handler=GetTreeHandler(d);
+ mImageAdder.SetCurrentDatabase(d);
+ mImageAdder.SetTreeHandler(handler);
+ mImageAdder.SetTimestampHandler(mTimestampDatabase);
+ mImageAdder.SetSynchronizer(mSynchronizer);
+ return mImageAdder.Synchronize(repair, checkAttributes);
+ }
//========================================================================
///
- void Gimmick::PrintLocalDatabase()
+ void Gimmick::Print(const std::string& d)
{
- mLocalDatabase->GetTree().Print();
+ GetTreeHandler(d)->GetTree().Print();
}
//========================================================================
+ void Gimmick::GetSetting(const std::string& name, std::string& value)
+ {
+ value = mSettings->getValue(name);
+ }
+ //========================================================================
+
+ //========================================================================
+
+ void Gimmick::UpdateSetting(const std::string& name, const std::string& value)
+ {
+ mSettings->updateSetting(name,value);
+ mSettings->writeSettingsFile();
+ }
+ //========================================================================
+
+ void Gimmick::DeleteDrive(const std::string& drive)
+ {
+ for( TreeHandlerMapType::const_iterator it = mTreeHandlerMap.begin();
+ it!= mTreeHandlerMap.end(); ++it)
+ {
+ mImageAdder.SetTreeHandler(it->second);
+ mImageAdder.DeleteDriveFromMainDB(drive);
+ }
+ mImageAdder.SetTimestampHandler(mTimestampDatabase);
+ mImageAdder.SetSynchronizer(mSynchronizer);
+ mImageAdder.DeleteDriveFromOtherDB(drive);
+ }
+ //========================================================================
+ void Gimmick::EditField(tree::Node* node, const std::string& d, const std::string& name, const std::string& key, const std::string& val)
+ {
+ TreeHandler * handler=GetTreeHandler(d);
+ mImageAdder.SetCurrentDatabase(d);
+ mImageAdder.SetTreeHandler(handler);
+ mImageAdder.EditField(node,name,key,val);
+ }
+ //========================================================================
+
+
+ /////////////////////////////////////////////////////////////////////////
+ // add DB from Settings file //
+ // @param : - //
+ // return : - //
+ /////////////////////////////////////////////////////////////////////////
+ void Gimmick::addDBSettings()
+ {
+
+ std::string pathSettings = mSettings->getValue(SETTINGS_DBPATH);
+
+ // split to find all paths
+ std::vector<std::string> paths;
+ std::string separator = ";";
+ std::string::size_type last_pos = pathSettings.find_first_not_of(separator);
+ //find first separator
+ std::string::size_type pos = pathSettings.find_first_of(separator, last_pos);
+ while(std::string::npos != pos || std::string::npos != last_pos)
+ {
+ paths.push_back(pathSettings.substr(last_pos, pos - last_pos));
+ last_pos = pathSettings.find_first_not_of(separator, pos);
+ pos = pathSettings.find_first_of(separator, last_pos);
+ }
+
+ std::vector<std::string>::iterator it_path = paths.begin();
+ for(; it_path != paths.end(); ++it_path)
+ {
+ pos = it_path->find_last_of("\\");
+ last_pos = it_path->find_last_of(".");
+ std::string name = it_path->substr(pos +1, last_pos -pos-1 );
+ addDB(name, it_path->c_str());
+ }
+
+ }
+
}