1 #include <creaImageIOGimmick.h>
3 #include <creaImageIOSystem.h>
4 #include <boost/filesystem.hpp>
5 #include <boost/algorithm/string.hpp>
7 #ifndef PATH_MAX // If not defined yet : do it
15 //==============================================================
19 RegisterGimmickMessageTypes();
23 //==============================================================
27 //==============================================================
32 mSettings->writeSettingsFile();
40 //==============================================================
43 //==============================================================
44 void Gimmick::Initialize()
46 std::string i_nameDB = "Local database";
47 // Create the UserSettings dir if does not exist
48 CreateUserSettingsDirectory();
49 // Sets the current directory to the home dir
50 mCurrentDirectory = GetHomeDirectory();
51 mSynchronizer= new Synchronizer(GetUserSettingsDirectory());
53 mSettings = new Settings(mCurrentDirectory);
56 std::string dbpath = GetLocalDatabasePath();
57 // Create or open local database
58 std::string dpath= mCurrentDirectory + "/.gimmick/localdatabase_Descriptor.txt";
59 boost::algorithm::replace_all( dpath,
60 INVALID_FILE_SEPARATOR ,
61 VALID_FILE_SEPARATOR);
62 mLocalDatabase = createDB(i_nameDB, dpath, dbpath);
63 // Add it to the TreeHandlerMap
64 mTreeHandlerMap[i_nameDB] = mLocalDatabase;
66 //Add additional DB from user Settings
69 // Creates files and directories database
70 mTimestampDatabase = new TimestampDatabaseHandler(GetTimestampDatabasePath());
71 // Create or open local database
72 if (! boost::filesystem::exists( GetTimestampDatabasePath() ) )
74 std::string mess = "Timestamp database '";
75 mess += GetTimestampDatabasePath();
76 mess += "' does not exist : creating it";
77 GimmickMessage(1,mess<<std::endl);
79 if ( ! mTimestampDatabase->Create() )
81 GimmickError("ERROR CREATING '"<<GetTimestampDatabasePath()<<"'");
88 GimmickMessage(1,"Opening Timestamp database '"
89 <<GetTimestampDatabasePath()<<"' "
91 if ( ! mTimestampDatabase->Open() )
93 GimmickError("ERROR OPENING '"<<GetTimestampDatabasePath()<<"'");
100 ///////////////////////////////////////////////////////////////////////
101 // add DB to TreeHandler Map //
102 // @param i_name : DB name //
103 // @param i_location : DB location //
105 ///////////////////////////////////////////////////////////////////////
106 void Gimmick::addDB(const std::string &i_name,
107 const std::string &i_location)
109 if(mTreeHandlerMap.find(i_name) == mTreeHandlerMap.end())
111 mTreeHandlerMap[i_name] = new SQLiteTreeHandler(i_location);
112 mTreeHandlerMap[i_name]->Open(true);
113 mSettings->addDB(i_location);
118 ///////////////////////////////////////////////////////////////////////////
119 // create a DB from a attributes descriptor file for medical images //
120 // @param i_name : DB name //
121 // @param i_locDesc : location of descriptor file //
122 // @param i_locDB : location of DB //
123 // return : the SQLiteTreeHandler object on DB //
124 /////////////////////////////////////////////////////////////////////////
125 SQLiteTreeHandler *Gimmick::createDB(const std::string &i_name,
126 const std::string &i_locDesc,
127 const std::string &i_locDB)
129 SQLiteTreeHandler *sqlTreeH = new SQLiteTreeHandler(i_locDB);
130 // Create or open local database
131 if (! boost::filesystem::exists(i_locDB) )
133 std::string mess = "Local database '";
135 mess += "' does not exist : creating it";
136 GimmickMessage(1,mess<<std::endl);
138 // CREATING DB STRUCTURE
139 sqlTreeH->GetTree().GetDescriptor().createDescriptorfromFile(i_locDesc);
140 if ( ! sqlTreeH->Create(true) )
142 GimmickError("ERROR CREATING '"<<i_locDB<<"'");
144 sqlTreeH->SetAttribute(0,"Name",i_name);
149 GimmickMessage(1,"Opening local database '" <<i_locDB<< "' " << std::endl);
150 if ( !sqlTreeH->Open(true) )
152 GimmickError("ERROR OPENING '"<<i_locDB<<"'");
159 //==============================================================
160 void Gimmick::Finalize()
163 // delete SQLiteTreeHandler Object
164 for( TreeHandlerMapType::const_iterator it = mTreeHandlerMap.begin();
165 it!= mTreeHandlerMap.end(); ++it)
169 delete mTimestampDatabase;
171 //==============================================================
173 //================================================================
176 #define VALID_FILE_SEPARATOR "\\"
177 #define INVALID_FILE_SEPARATOR "/"
179 #define INVALID_FILE_SEPARATOR "\\"
180 #define VALID_FILE_SEPARATOR "/"
182 //================================================================
184 //================================================================
185 const std::string& Gimmick::GetHomeDirectory()
187 if (mHomeDirectory.size()==0)
189 #if defined(__GNUC__)
190 mHomeDirectory = getenv("HOME");
191 #elif defined(_WIN32)
192 mHomeDirectory = getenv("USERPROFILE");
195 return mHomeDirectory;
197 //================================================================
198 const std::string& Gimmick::GetUserSettingsDirectory()
200 if (mUserSettingsDirectory.size()==0)
202 mUserSettingsDirectory = GetHomeDirectory();
203 mUserSettingsDirectory += "/.gimmick/";
204 boost::algorithm::replace_all( mUserSettingsDirectory,
205 INVALID_FILE_SEPARATOR ,
206 VALID_FILE_SEPARATOR);
208 return mUserSettingsDirectory;
210 //================================================================
212 //================================================================
213 int Gimmick::GetBinaryDirectory(char *pname, size_t pathsize)
217 /* Oddly, the readlink(2) man page says no NULL is appended. */
218 /* So you have to do it yourself, based on the return value: */
219 pathsize --; /* Preserve a space to add the trailing NULL */
220 long result = readlink("/proc/self/exe", pname, pathsize);
223 pname[result] = 0; /* add the #@!%ing NULL */
225 if ((access(pname, 0) == 0))
226 return 0; /* file exists, return OK */
227 /*else name doesn't seem to exist, return FAIL (falls
233 long result = GetModuleFileName(NULL, pname, pathsize);
236 /* fix up the dir slashes... */
237 int len = strlen(pname);
239 for (idx = 0; idx < len; idx++)
241 if (pname[idx] == '\\') pname[idx] = '/';
244 for (idx = len-1; idx >=0 ; idx--)
246 if (pname[idx] == '/')
253 if ((access(pname, 0) == 0))
254 return 0; /* file exists, return OK */
255 /*else name doesn't seem to exist, return FAIL (falls
261 char *p = getexecname();
264 /* According to the Sun manpages, getexecname will
265 "normally" return an */
266 /* absolute path - BUT might not... AND that IF it is not,
268 /* getcwd() will "usually" be the correct thing... Urgh!
271 /* check pathname is absolute (begins with a / ???) */
272 if (p[0] == '/') /* assume this means we have an
275 strncpy(pname, p, pathsize);
276 if ((access(pname, 0) == 0))
277 return 0; /* file exists, return OK */
279 else /* if not, prepend getcwd() then check if file
282 getcwd(pname, pathsize);
283 long result = strlen(pname);
284 strncat(pname, "/", (pathsize - result));
286 strncat(pname, p, (pathsize - result));
288 if ((access(pname, 0) == 0))
289 return 0; /* file exists, return OK */
290 /*else name doesn't seem to exist, return FAIL
296 #ifdef MACOSX /* assume this is OSX */
298 from http://www.hmug.org/man/3/NSModule.html
300 extern int _NSGetExecutablePath(char *buf, unsigned long
303 _NSGetExecutablePath copies the path of the executable
304 into the buffer and returns 0 if the path was successfully
305 copied in the provided buffer. If the buffer is not large
306 enough, -1 is returned and the expected buffer size is
307 copied in *bufsize. Note that _NSGetExecutablePath will
308 return "a path" to the executable not a "real path" to the
309 executable. That is the path may be a symbolic link and
310 not the real file. And with deep directories the total
311 bufsize needed could be more than MAXPATHLEN.
315 char *given_path = (char*)malloc(MAXPATHLEN * 2);
316 if (!given_path) return status;
318 uint32_t npathsize = MAXPATHLEN * 2;
319 long result = _NSGetExecutablePath(given_path, &npathsize);
321 { /* OK, we got something - now try and resolve the real path...
323 if (realpath(given_path, pname) != NULL)
325 if ((access(pname, 0) == 0))
326 status = 0; /* file exists, return OK */
333 return -1; /* Path Lookup Failed */
336 //================================================================
337 const std::string& Gimmick::GetLocalDatabasePath()
339 if (mLocalDatabasePath.size()==0)
341 mLocalDatabasePath = GetUserSettingsDirectory();
342 mLocalDatabasePath += "local_database.sqlite3";
343 boost::algorithm::replace_all( mLocalDatabasePath,
344 INVALID_FILE_SEPARATOR ,
345 VALID_FILE_SEPARATOR);
347 return mLocalDatabasePath;
350 //================================================================
352 //================================================================
353 const std::string& Gimmick::GetTimestampDatabasePath()
355 if (mTimestampDatabasePath.size()==0)
357 mTimestampDatabasePath = GetUserSettingsDirectory();
358 mTimestampDatabasePath += "timestamp_database.sqlite3";
359 boost::algorithm::replace_all( mTimestampDatabasePath,
360 INVALID_FILE_SEPARATOR ,
361 VALID_FILE_SEPARATOR);
363 return mTimestampDatabasePath;
365 //========================================================================
367 //========================================================================
368 void Gimmick::CreateUserSettingsDirectory()
370 if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) )
372 GimmickMessage(1,"Directory '"<<GetUserSettingsDirectory()<<"' "
373 << "does not exist : creating it"<<std::endl);
375 if ( ! boost::filesystem::create_directory( GetUserSettingsDirectory() ) )
377 GimmickError("ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
381 std::string setDir=GetUserSettingsDirectory();
382 boost::algorithm::replace_all( setDir,
383 INVALID_FILE_SEPARATOR ,
384 VALID_FILE_SEPARATOR);
385 setDir+="localdatabase_Descriptor.txt";
386 //if(!boost::filesystem::is_regular_file(setDir)) //JPRX
387 if(!boost::filesystem::is_regular(setDir))
390 int err = GetBinaryDirectory(name, PATH_MAX);
391 std::string path=name;
392 path=path.substr(0,path.size()-1);
393 path=path.substr(0,path.find_last_of("/"));
394 path+="/data/localdatabase_Descriptor.txt";
395 boost::algorithm::replace_all( path,
396 INVALID_FILE_SEPARATOR ,
397 VALID_FILE_SEPARATOR);
398 boost::filesystem::copy_file(path,setDir);
401 //========================================================================
404 //========================================================================
405 /// Sets message level
406 void Gimmick::SetMessageLevel(int l)
408 SetGimmickMessageLevel(l);
410 //========================================================================
412 //========================================================================
413 /// Sets message level
414 void Gimmick::SetDebugMessageLevel(int l)
416 SetGimmickDebugMessageLevel(l);
418 //========================================================================
420 //========================================================================
421 /// Returns the tree handler with the given name
422 TreeHandler* Gimmick::GetTreeHandler(const std::string& name) const
424 TreeHandlerMapType::const_iterator i;
425 i = GetTreeHandlerMap().find(name);
426 if ( i == GetTreeHandlerMap().end() )
428 GimmickError("TreeHandler '"<<name<<"' does not exist");
433 //========================================================================
434 ///Returns the timestamp database handler
435 TimestampDatabaseHandler* Gimmick::GetTimestampDatabase() const
437 return mTimestampDatabase;
441 //========================================================================
442 /// Add the files to the tree handler
443 void Gimmick::AddFiles(const std::string& d,
444 const std::vector<std::string>& filenames)
446 GimmickMessage(2,"Adding files to '"<<d<<"'"<<std::endl);
448 mImageAdder.SetCurrentDatabase(d);
449 mImageAdder.SetTreeHandler(GetTreeHandler(d));
450 mImageAdder.SetTimestampHandler(mTimestampDatabase);
451 mImageAdder.SetSynchronizer(mSynchronizer);
452 mImageAdder.AddFiles(filenames);
455 //========================================================================
457 //========================================================================
458 /// Add a dir to the local database
459 void Gimmick::AddDir(const std::string& d, const std::string& f,
462 GimmickMessage(2,"Adding dir '"<<f<<"' to '"<<d<<"' recurse:"
463 <<recurse<<std::endl);
465 TreeHandler * handler=GetTreeHandler(d);
466 mImageAdder.SetCurrentDatabase(d);
467 mImageAdder.SetTreeHandler(handler);
468 mImageAdder.SetTimestampHandler(mTimestampDatabase);
469 mImageAdder.SetSynchronizer(mSynchronizer);
470 mImageAdder.AddDirectory(f,recurse);
473 //========================================================================
475 //========================================================================
476 void Gimmick::RemoveFile(const std::string& d,
479 mImageAdder.SetCurrentDatabase(d);
480 mImageAdder.SetSynchronizer(mSynchronizer);
481 mTimestampDatabase->RemoveNode("PATH",node,d);
482 mImageAdder.RemoveFile(node);
484 //========================================================================
486 //========================================================================
488 void Gimmick::CopyFiles(const std::vector<std::string>& filenames, const std::string& d )
490 TreeHandler * handler=GetTreeHandler(d);
491 mImageAdder.SetCurrentDatabase(d);
492 mImageAdder.SetTreeHandler(handler);
493 mImageAdder.SetTimestampHandler(mTimestampDatabase);
494 mImageAdder.SetSynchronizer(mSynchronizer);
495 mImageAdder.CopyFiles(filenames, mSettings->getValue(SETTINGS_COPY_PATH));
498 //========================================================================
500 std::string Gimmick::Synchronize(const std::string& d, bool repair, bool checkAttributes)
502 TreeHandler * handler=GetTreeHandler(d);
503 mImageAdder.SetCurrentDatabase(d);
504 mImageAdder.SetTreeHandler(handler);
505 mImageAdder.SetTimestampHandler(mTimestampDatabase);
506 mImageAdder.SetSynchronizer(mSynchronizer);
507 return mImageAdder.Synchronize(repair, checkAttributes);
510 //========================================================================
512 void Gimmick::Print(const std::string& d)
514 GetTreeHandler(d)->GetTree().Print();
516 //========================================================================
518 void Gimmick::GetSetting(const std::string& name, std::string& value)
520 value = mSettings->getValue(name);
522 //========================================================================
524 //========================================================================
526 void Gimmick::GetAttributes(const std::string& d,
527 const std::string& filename,
528 const std::vector<std::string>& params,
529 std::vector<std::string>& results)
531 TreeHandler * handler=GetTreeHandler(d);
532 mImageAdder.SetCurrentDatabase(d);
533 mImageAdder.SetTreeHandler(handler);
534 mImageAdder.SetTimestampHandler(mTimestampDatabase);
535 mImageAdder.SetSynchronizer(mSynchronizer);
536 mImageAdder.GetAttributes(params, filename, results);
538 //========================================================================
540 //========================================================================
542 void Gimmick::UpdateSetting(const std::string& name, const std::string& value)
544 mSettings->updateSetting(name,value);
545 mSettings->writeSettingsFile();
547 //========================================================================
549 void Gimmick::DeleteDrive(const std::string& drive)
551 for( TreeHandlerMapType::const_iterator it = mTreeHandlerMap.begin();
552 it!= mTreeHandlerMap.end(); ++it)
554 mImageAdder.SetTreeHandler(it->second);
555 mImageAdder.DeleteDriveFromMainDB(drive);
557 mImageAdder.SetTimestampHandler(mTimestampDatabase);
558 mImageAdder.SetSynchronizer(mSynchronizer);
559 mImageAdder.DeleteDriveFromOtherDB(drive);
562 //========================================================================
563 void Gimmick::EditField(tree::Node* node, const std::string& d, const std::string& name, const std::string& key, const std::string& val)
565 TreeHandler * handler=GetTreeHandler(d);
566 mImageAdder.SetCurrentDatabase(d);
567 mImageAdder.SetTreeHandler(handler);
568 mImageAdder.EditField(node,name,key,val);
570 //========================================================================
573 /////////////////////////////////////////////////////////////////////////
574 // add DB from Settings file //
577 /////////////////////////////////////////////////////////////////////////
578 void Gimmick::addDBSettings()
581 std::string pathSettings = mSettings->getValue(SETTINGS_DBPATH);
583 // split to find all paths
584 std::vector<std::string> paths;
585 std::string separator = ";";
586 std::string::size_type last_pos = pathSettings.find_first_not_of(separator);
587 //find first separator
588 std::string::size_type pos = pathSettings.find_first_of(separator, last_pos);
589 while(std::string::npos != pos || std::string::npos != last_pos)
591 paths.push_back(pathSettings.substr(last_pos, pos - last_pos));
592 last_pos = pathSettings.find_first_not_of(separator, pos);
593 pos = pathSettings.find_first_of(separator, last_pos);
596 std::vector<std::string>::iterator it_path = paths.begin();
597 for(; it_path != paths.end(); ++it_path)
599 pos = it_path->find_last_of("\\");
600 last_pos = it_path->find_last_of(".");
601 std::string name = it_path->substr(pos +1, last_pos -pos-1 );
602 addDB(name, it_path->c_str());