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 mLocalDatabase = createDB(i_nameDB, mCurrentDirectory + "\\.gimmick\\localdatabase_Descriptor.txt", dbpath);
59 // Add it to the TreeHandlerMap
60 mTreeHandlerMap[i_nameDB] = mLocalDatabase;
62 //Add additional DB from user Settings
65 // Creates files and directories database
66 mTimestampDatabase = new TimestampDatabaseHandler(GetTimestampDatabasePath());
67 // Create or open local database
68 if (! boost::filesystem::exists( GetTimestampDatabasePath() ) )
70 std::string mess = "Timestamp database '";
71 mess += GetTimestampDatabasePath();
72 mess += "' does not exist : creating it";
73 GimmickMessage(1,mess<<std::endl);
75 if ( ! mTimestampDatabase->Create() )
77 GimmickError("ERROR CREATING '"<<GetTimestampDatabasePath()<<"'");
84 GimmickMessage(1,"Opening Timestamp database '"
85 <<GetTimestampDatabasePath()<<"' "
87 if ( ! mTimestampDatabase->Open() )
89 GimmickError("ERROR OPENING '"<<GetTimestampDatabasePath()<<"'");
96 ///////////////////////////////////////////////////////////////////////
97 // add DB to TreeHandler Map //
98 // @param i_name : DB name //
99 // @param i_location : DB location //
101 ///////////////////////////////////////////////////////////////////////
102 void Gimmick::addDB(const std::string &i_name,
103 const std::string &i_location)
105 if(mTreeHandlerMap.find(i_name) == mTreeHandlerMap.end())
107 mTreeHandlerMap[i_name] = new SQLiteTreeHandler(i_location);
108 mTreeHandlerMap[i_name]->Open(true);
109 mSettings->addDB(i_location);
114 ///////////////////////////////////////////////////////////////////////////
115 // create a DB from a attributes descriptor file for medical images //
116 // @param i_name : DB name //
117 // @param i_locDesc : location of descriptor file //
118 // @param i_locDB : location of DB //
119 // return : the SQLiteTreeHandler object on DB //
120 /////////////////////////////////////////////////////////////////////////
121 SQLiteTreeHandler *Gimmick::createDB(const std::string &i_name,
122 const std::string &i_locDesc,
123 const std::string &i_locDB)
125 SQLiteTreeHandler *sqlTreeH = new SQLiteTreeHandler(i_locDB);
126 // Create or open local database
127 if (! boost::filesystem::exists(i_locDB) )
129 std::string mess = "Local database '";
131 mess += "' does not exist : creating it";
132 GimmickMessage(1,mess<<std::endl);
134 // CREATING DB STRUCTURE
135 sqlTreeH->GetTree().GetDescriptor().createDescriptorfromFile(i_locDesc);
136 if ( ! sqlTreeH->Create(true) )
138 GimmickError("ERROR CREATING '"<<i_locDB<<"'");
140 sqlTreeH->SetAttribute(0,"Name",i_name);
145 GimmickMessage(1,"Opening local database '" <<i_locDB<< "' " << std::endl);
146 if ( !sqlTreeH->Open(true) )
148 GimmickError("ERROR OPENING '"<<i_locDB<<"'");
155 //==============================================================
156 void Gimmick::Finalize()
159 // delete SQLiteTreeHandler Object
160 for( TreeHandlerMapType::const_iterator it = mTreeHandlerMap.begin();
161 it!= mTreeHandlerMap.end(); ++it)
165 delete mTimestampDatabase;
167 //==============================================================
169 //================================================================
172 #define VALID_FILE_SEPARATOR "\\"
173 #define INVALID_FILE_SEPARATOR "/"
175 #define INVALID_FILE_SEPARATOR "\\"
176 #define VALID_FILE_SEPARATOR "/"
178 //================================================================
180 //================================================================
181 const std::string& Gimmick::GetHomeDirectory()
183 if (mHomeDirectory.size()==0)
185 #if defined(__GNUC__)
186 mHomeDirectory = getenv("HOME");
187 #elif defined(_WIN32)
188 mHomeDirectory = getenv("USERPROFILE");
191 return mHomeDirectory;
193 //================================================================
194 const std::string& Gimmick::GetUserSettingsDirectory()
196 if (mUserSettingsDirectory.size()==0)
198 mUserSettingsDirectory = GetHomeDirectory();
199 mUserSettingsDirectory += "/.gimmick/";
200 boost::algorithm::replace_all( mUserSettingsDirectory,
201 INVALID_FILE_SEPARATOR ,
202 VALID_FILE_SEPARATOR);
204 return mUserSettingsDirectory;
206 //================================================================
208 //================================================================
209 int Gimmick::GetBinaryDirectory(char *pname, size_t pathsize)
213 /* Oddly, the readlink(2) man page says no NULL is appended. */
214 /* So you have to do it yourself, based on the return value: */
215 pathsize --; /* Preserve a space to add the trailing NULL */
216 long result = readlink("/proc/self/exe", pname, pathsize);
219 pname[result] = 0; /* add the #@!%ing NULL */
221 if ((access(pname, 0) == 0))
222 return 0; /* file exists, return OK */
223 /*else name doesn't seem to exist, return FAIL (falls
229 long result = GetModuleFileName(NULL, pname, pathsize);
232 /* fix up the dir slashes... */
233 int len = strlen(pname);
235 for (idx = 0; idx < len; idx++)
237 if (pname[idx] == '\\') pname[idx] = '/';
240 for (idx = len-1; idx >=0 ; idx--)
242 if (pname[idx] == '/')
249 if ((access(pname, 0) == 0))
250 return 0; /* file exists, return OK */
251 /*else name doesn't seem to exist, return FAIL (falls
257 char *p = getexecname();
260 /* According to the Sun manpages, getexecname will
261 "normally" return an */
262 /* absolute path - BUT might not... AND that IF it is not,
264 /* getcwd() will "usually" be the correct thing... Urgh!
267 /* check pathname is absolute (begins with a / ???) */
268 if (p[0] == '/') /* assume this means we have an
271 strncpy(pname, p, pathsize);
272 if ((access(pname, 0) == 0))
273 return 0; /* file exists, return OK */
275 else /* if not, prepend getcwd() then check if file
278 getcwd(pname, pathsize);
279 long result = strlen(pname);
280 strncat(pname, "/", (pathsize - result));
282 strncat(pname, p, (pathsize - result));
284 if ((access(pname, 0) == 0))
285 return 0; /* file exists, return OK */
286 /*else name doesn't seem to exist, return FAIL
292 #ifdef MACOSX /* assume this is OSX */
294 from http://www.hmug.org/man/3/NSModule.html
296 extern int _NSGetExecutablePath(char *buf, unsigned long
299 _NSGetExecutablePath copies the path of the executable
300 into the buffer and returns 0 if the path was successfully
301 copied in the provided buffer. If the buffer is not large
302 enough, -1 is returned and the expected buffer size is
303 copied in *bufsize. Note that _NSGetExecutablePath will
304 return "a path" to the executable not a "real path" to the
305 executable. That is the path may be a symbolic link and
306 not the real file. And with deep directories the total
307 bufsize needed could be more than MAXPATHLEN.
311 char *given_path = (char*)malloc(MAXPATHLEN * 2);
312 if (!given_path) return status;
314 uint32_t npathsize = MAXPATHLEN * 2;
315 long result = _NSGetExecutablePath(given_path, &npathsize);
317 { /* OK, we got something - now try and resolve the real path...
319 if (realpath(given_path, pname) != NULL)
321 if ((access(pname, 0) == 0))
322 status = 0; /* file exists, return OK */
329 return -1; /* Path Lookup Failed */
332 //================================================================
333 const std::string& Gimmick::GetLocalDatabasePath()
335 if (mLocalDatabasePath.size()==0)
337 mLocalDatabasePath = GetUserSettingsDirectory();
338 mLocalDatabasePath += "local_database.sqlite3";
339 boost::algorithm::replace_all( mLocalDatabasePath,
340 INVALID_FILE_SEPARATOR ,
341 VALID_FILE_SEPARATOR);
343 return mLocalDatabasePath;
346 //================================================================
348 //================================================================
349 const std::string& Gimmick::GetTimestampDatabasePath()
351 if (mTimestampDatabasePath.size()==0)
353 mTimestampDatabasePath = GetUserSettingsDirectory();
354 mTimestampDatabasePath += "timestamp_database.sqlite3";
355 boost::algorithm::replace_all( mTimestampDatabasePath,
356 INVALID_FILE_SEPARATOR ,
357 VALID_FILE_SEPARATOR);
359 return mTimestampDatabasePath;
361 //========================================================================
363 //========================================================================
364 void Gimmick::CreateUserSettingsDirectory()
366 if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) )
368 GimmickMessage(1,"Directory '"<<GetUserSettingsDirectory()<<"' "
369 << "does not exist : creating it"<<std::endl);
371 if ( ! boost::filesystem::create_directory( GetUserSettingsDirectory() ) )
373 GimmickError("ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
377 std::string setDir=GetUserSettingsDirectory();
378 boost::algorithm::replace_all( setDir,
379 INVALID_FILE_SEPARATOR ,
380 VALID_FILE_SEPARATOR);
381 setDir+="localdatabase_Descriptor.txt";
382 //if(!boost::filesystem::is_regular_file(setDir)) //JPRX
383 if(!boost::filesystem::is_regular(setDir))
386 int err = GetBinaryDirectory(name, PATH_MAX);
387 std::string path=name;
388 path=path.substr(0,path.size()-1);
389 path=path.substr(0,path.find_last_of("/"));
390 path+="/data/localdatabase_Descriptor.txt";
391 boost::algorithm::replace_all( path,
392 INVALID_FILE_SEPARATOR ,
393 VALID_FILE_SEPARATOR);
394 boost::filesystem::copy_file(path,setDir);
397 //========================================================================
400 //========================================================================
401 /// Sets message level
402 void Gimmick::SetMessageLevel(int l)
404 SetGimmickMessageLevel(l);
406 //========================================================================
408 //========================================================================
409 /// Sets message level
410 void Gimmick::SetDebugMessageLevel(int l)
412 SetGimmickDebugMessageLevel(l);
414 //========================================================================
416 //========================================================================
417 /// Returns the tree handler with the given name
418 TreeHandler* Gimmick::GetTreeHandler(const std::string& name) const
420 TreeHandlerMapType::const_iterator i;
421 i = GetTreeHandlerMap().find(name);
422 if ( i == GetTreeHandlerMap().end() )
424 GimmickError("TreeHandler '"<<name<<"' does not exist");
429 //========================================================================
430 ///Returns the timestamp database handler
431 TimestampDatabaseHandler* Gimmick::GetTimestampDatabase() const
433 return mTimestampDatabase;
437 //========================================================================
438 /// Add the files to the tree handler
439 void Gimmick::AddFiles(const std::string& d,
440 const std::vector<std::string>& filenames)
442 GimmickMessage(2,"Adding files to '"<<d<<"'"<<std::endl);
444 mImageAdder.SetCurrentDatabase(d);
445 mImageAdder.SetTreeHandler(GetTreeHandler(d));
446 mImageAdder.SetTimestampHandler(mTimestampDatabase);
447 mImageAdder.SetSynchronizer(mSynchronizer);
448 mImageAdder.AddFiles(filenames);
451 //========================================================================
453 //========================================================================
454 /// Add a dir to the local database
455 void Gimmick::AddDir(const std::string& d, const std::string& f,
458 GimmickMessage(2,"Adding dir '"<<f<<"' to '"<<d<<"' recurse:"
459 <<recurse<<std::endl);
461 TreeHandler * handler=GetTreeHandler(d);
462 mImageAdder.SetCurrentDatabase(d);
463 mImageAdder.SetTreeHandler(handler);
464 mImageAdder.SetTimestampHandler(mTimestampDatabase);
465 mImageAdder.SetSynchronizer(mSynchronizer);
466 mImageAdder.AddDirectory(f,recurse);
469 //========================================================================
471 //========================================================================
472 void Gimmick::RemoveFile(const std::string& d,
475 mImageAdder.SetCurrentDatabase(d);
476 mImageAdder.SetSynchronizer(mSynchronizer);
477 mTimestampDatabase->RemoveNode("PATH",node,d);
478 mImageAdder.RemoveFile(node);
480 //========================================================================
482 //========================================================================
484 void Gimmick::CopyFiles(const std::vector<std::string>& filenames, const std::string& d )
486 TreeHandler * handler=GetTreeHandler(d);
487 mImageAdder.SetCurrentDatabase(d);
488 mImageAdder.SetTreeHandler(handler);
489 mImageAdder.SetTimestampHandler(mTimestampDatabase);
490 mImageAdder.SetSynchronizer(mSynchronizer);
491 mImageAdder.CopyFiles(filenames, mSettings->getValue(SETTINGS_COPY_PATH));
494 //========================================================================
496 std::string Gimmick::Synchronize(const std::string& d, bool repair, bool checkAttributes)
498 TreeHandler * handler=GetTreeHandler(d);
499 mImageAdder.SetCurrentDatabase(d);
500 mImageAdder.SetTreeHandler(handler);
501 mImageAdder.SetTimestampHandler(mTimestampDatabase);
502 mImageAdder.SetSynchronizer(mSynchronizer);
503 return mImageAdder.Synchronize(repair, checkAttributes);
506 //========================================================================
508 void Gimmick::Print(const std::string& d)
510 GetTreeHandler(d)->GetTree().Print();
512 //========================================================================
514 void Gimmick::GetSetting(const std::string& name, std::string& value)
516 value = mSettings->getValue(name);
518 //========================================================================
520 //========================================================================
522 void Gimmick::GetAttributes(const std::string& d,
523 const std::string& filename,
524 const std::vector<std::string>& params,
525 std::vector<std::string>& results)
527 TreeHandler * handler=GetTreeHandler(d);
528 mImageAdder.SetCurrentDatabase(d);
529 mImageAdder.SetTreeHandler(handler);
530 mImageAdder.SetTimestampHandler(mTimestampDatabase);
531 mImageAdder.SetSynchronizer(mSynchronizer);
532 mImageAdder.GetAttributes(params, filename, results);
534 //========================================================================
536 //========================================================================
538 void Gimmick::UpdateSetting(const std::string& name, const std::string& value)
540 mSettings->updateSetting(name,value);
541 mSettings->writeSettingsFile();
543 //========================================================================
545 void Gimmick::DeleteDrive(const std::string& drive)
547 for( TreeHandlerMapType::const_iterator it = mTreeHandlerMap.begin();
548 it!= mTreeHandlerMap.end(); ++it)
550 mImageAdder.SetTreeHandler(it->second);
551 mImageAdder.DeleteDriveFromMainDB(drive);
553 mImageAdder.SetTimestampHandler(mTimestampDatabase);
554 mImageAdder.SetSynchronizer(mSynchronizer);
555 mImageAdder.DeleteDriveFromOtherDB(drive);
558 //========================================================================
559 void Gimmick::EditField(tree::Node* node, const std::string& d, const std::string& name, const std::string& key, const std::string& val)
561 TreeHandler * handler=GetTreeHandler(d);
562 mImageAdder.SetCurrentDatabase(d);
563 mImageAdder.SetTreeHandler(handler);
564 mImageAdder.EditField(node,name,key,val);
566 //========================================================================
569 /////////////////////////////////////////////////////////////////////////
570 // add DB from Settings file //
573 /////////////////////////////////////////////////////////////////////////
574 void Gimmick::addDBSettings()
577 std::string pathSettings = mSettings->getValue(SETTINGS_DBPATH);
579 // split to find all paths
580 std::vector<std::string> paths;
581 std::string separator = ";";
582 std::string::size_type last_pos = pathSettings.find_first_not_of(separator);
583 //find first separator
584 std::string::size_type pos = pathSettings.find_first_of(separator, last_pos);
585 while(std::string::npos != pos || std::string::npos != last_pos)
587 paths.push_back(pathSettings.substr(last_pos, pos - last_pos));
588 last_pos = pathSettings.find_first_not_of(separator, pos);
589 pos = pathSettings.find_first_of(separator, last_pos);
592 std::vector<std::string>::iterator it_path = paths.begin();
593 for(; it_path != paths.end(); ++it_path)
595 pos = it_path->find_last_of("\\");
596 last_pos = it_path->find_last_of(".");
597 std::string name = it_path->substr(pos +1, last_pos -pos-1 );
598 addDB(name, it_path->c_str());