Spinning Topp Logo BlackTopp Studios
inc
objectsettings.cpp
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _objectsettings_cpp
41 #define _objectsettings_cpp
42 
43 #include "objectsettings.h"
44 #include "stringtool.h"
46 #include "Resource/resourceutilities.h"
47 #include "Resource/filestream.h"
48 
49 namespace Mezzanine
50 {
51  ///////////////////////////////////////////////////////////////////////////////
52  // ObjectSettingSetContainer Methods
53 
55  ContainerName(Name)
56  { }
57 
59  { this->DestroyAllObjectSettingSets(); }
60 
61  ///////////////////////////////////////////////////////////////////////////////
62  // Utility
63 
65  { this->ContainerName = Name; }
66 
68  { return ContainerName; }
69 
70  ///////////////////////////////////////////////////////////////////////////////
71  // Sub-Set Methods
72 
74  {
75  ObjectSettingSet* NewSubSet = new ObjectSettingSet( Name );
76  NewSubSet->ParentSetOrGroup = this;
77  this->SubSets.push_back( NewSubSet );
78  return NewSubSet;
79  }
80 
82  {
83  ToBeAdded->ParentSetOrGroup = this;
84  this->_MarkUpdated();
85  this->SubSets.push_back( ToBeAdded );
86  }
87 
89  {
90  for( ConstSubSetIterator it = this->SubSets.begin() ; it != this->SubSets.end() ; ++it )
91  {
92  if( Name == (*it)->GetName() ) {
93  if(0 == Which) return (*it);
94  else --Which;
95  }
96  }
97  return NULL;
98  }
99 
101  {
102  return this->SubSets.at(Index);
103  }
104 
106  {
107  for( SubSetIterator it = this->SubSets.begin() ; it != this->SubSets.end() ; ++it )
108  {
109  if( ToBeRemoved == (*it) ) {
110  ToBeRemoved->ParentSetOrGroup = NULL;
111  this->SubSets.erase(it);
112  this->_MarkUpdated();
113  return;
114  }
115  }
116  }
117 
119  {
120  for( SubSetIterator it = this->SubSets.begin() ; it != this->SubSets.end() ; ++it )
121  {
122  if( Name == (*it)->GetName() ) {
123  delete (*it);
124  this->SubSets.erase(it);
125  return;
126  }
127  }
128  }
129 
131  {
132  if( this->SubSets.empty() )
133  return;
134  for( SubSetIterator it = this->SubSets.begin() ; it != this->SubSets.end() ; ++it )
135  {
136  (*it)->ParentSetOrGroup = NULL;
137  delete (*it);
138  }
139  this->SubSets.clear();
140  }
141 
142  ///////////////////////////////////////////////////////////////////////////////
143  // Iterator Access
144 
146  { return this->SubSets.begin(); }
147 
149  { return this->SubSets.begin(); }
150 
152  { return this->SubSets.end(); }
153 
155  { return this->SubSets.end(); }
156 
157  ///////////////////////////////////////////////////////////////////////////////
158  // ObjectSettingSet Methods
159 
162  ParentSetOrGroup(NULL)
163  { }
164 
166  { }
167 
168  ///////////////////////////////////////////////////////////////////////////////
169  // Utility
170 
172  { return this->ParentSetOrGroup; }
173 
174  ///////////////////////////////////////////////////////////////////////////////
175  // Setting Methods
176 
177  void ObjectSettingSet::SetSettingValue(const String& SettingName, const String& StringValue)
178  {
179  this->Settings.insert( std::pair<String,String>(SettingName,StringValue) );
180  this->_MarkUpdated();
181  }
182 
184  {
185  ConstSettingsIterator SetIt = this->Settings.find( SettingName );
186  if( SetIt != this->Settings.end() ) return (*SetIt).second;
187  else return "";
188  }
189 
190  ///////////////////////////////////////////////////////////////////////////////
191  // Iterator Access
192 
194  { return this->Settings.begin(); }
195 
197  { return this->Settings.begin(); }
198 
200  { return this->Settings.end(); }
201 
203  { return this->Settings.end(); }
204 
206  {
207  if( this->ParentSetOrGroup )
209  }
210 
211  ///////////////////////////////////////////////////////////////////////////////
212  // ObjectSettingGroup Methods
213 
216  OptionalFile(NULL)
217  { }
218 
220  { }
221 
222  ///////////////////////////////////////////////////////////////////////////////
223  // Optional File config
224 
226  { return this->OptionalFile; }
227 
229  { return ( this->OptionalFile ? this->OptionalFile->GetFileName() : StringTools::Blank ); }
230 
231  ///////////////////////////////////////////////////////////////////////////////
232  // Internal Methods
233 
235  {
236  if( this->OptionalFile )
237  this->OptionalFile->SetNeedsSave(true);
238  }
239 
241  {
242  this->OptionalFile = File;
243  this->_MarkUpdated();
244  }
245 
246  ///////////////////////////////////////////////////////////////////////////////
247  // ObjectSettingFile Methods
248 
250  File(FileName),
251  NeedsSave(false)
252  { }
253 
255  { }
256 
257  ///////////////////////////////////////////////////////////////////////////////
258  // File and Group Management
259 
261  { return this->File; }
262 
264  { this->NeedsSave = Save; }
265 
267  { return this->NeedsSave; }
268 
270  {
271  Group->_SetOptionalFile(this);
272  this->SaveGroups.push_back(Group);
273  this->NeedsSave = true;
274  }
275 
277  {
278  for( ConstSaveGroupsIterator SaveIt = this->SaveGroups.begin() ; SaveIt != this->SaveGroups.end() ; ++SaveIt )
279  {
280  if( Name == (*SaveIt)->GetName() )
281  return (*SaveIt);
282  }
283  return NULL;
284  }
285 
287  {
288  for( SaveGroupsIterator SaveIt = this->SaveGroups.begin() ; SaveIt != this->SaveGroups.end() ; ++SaveIt )
289  {
290  if( Group == (*SaveIt) ) {
291  Group->_SetOptionalFile(NULL);
292  this->SaveGroups.erase(SaveIt);
293  this->NeedsSave = true;
294  return;
295  }
296  }
297  }
298 
300  { return this->SaveGroups; }
301 
303  { return this->SaveGroups.begin(); }
304 
306  { return this->SaveGroups.begin(); }
307 
309  { return this->SaveGroups.end(); }
310 
312  { return this->SaveGroups.end(); }
313 
314  ///////////////////////////////////////////////////////////////////////////////
315  // ObjectSettingsHandler Methods
316 
318  AutoGenPath(true),
319  AutoGenFiles(true)
320  { }
321 
323  { }
324 
326  {
328  XML::Document SettingsDoc;
329  // Open the stream and load the document
330  try
331  {
332  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
333  Resource::FileStream SettingsStream(FileName,Path);
334  SettingsDoc.Load(SettingsStream);
335  }
336  catch( FileNotFoundException Ex )
337  {
338  // File doesn't exist, just exit. If the user wants to autogen it will be autogen'd later.
339  return RetVec;
340  }
341 
342  // Load and parse the settings
343  XML::Node RootNode = SettingsDoc.GetChild(GetObjectRootNodeName());
344  if( !RootNode.Empty() ) {
345  XML::Node CurrentSettingsNode = RootNode.GetChild("Current");
346  if( !RootNode.Empty() ) {
347  if( !this->CurrentSettingsSaveFile.empty() ) {
348  MEZZ_EXCEPTION(ExceptionBase::II_DUPLICATE_IDENTITY_EXCEPTION,"Second file containing \"Current\" settings detected.");
349  }
350  this->CurrentSettingsSaveFile = FileName;
351  }
352 
353  // Store the settings for a moment, since we have some extra stuff to do with them.
354  RetVec = this->LoadSettingsFromXML(RootNode);
355 
356  ObjectSettingFile* NewSetFile = this->CreateSettingFile(FileName);
357  for( SettingGroupVector::iterator It = RetVec->begin() ; It != RetVec->end() ; ++It )
358  NewSetFile->AddGroup( (*It) );
359  return RetVec;
360  }else{
361  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_INVALID_EXCEPTION,"Attempting to parse XML which does not contain valid ObjectRootNodeName. Searching for \"" + GetObjectRootNodeName() + "\", not found.");
362  }
363  }
364 
365  void ObjectSettingsHandler::SaveSettingsToFile(StringVector& GroupNames, const String& FileName, const String& Path)
366  {
367  XML::Document SettingsDoc;
368  XML::Node DeclNode = SettingsDoc.AppendChild(XML::NodeDeclaration);
369  XML::Attribute VerAttrib = DeclNode.AppendAttribute("version");
370  if( DeclNode.SetName("xml") && VerAttrib.SetValue("1.0") ) {
371  XML::Node RootNode = SettingsDoc.AppendChild( this->GetObjectRootNodeName() );
372 
373  if( GroupNames.empty() ) this->SaveSettingsToXML(RootNode);
374  else this->SaveSettingsToXML(GroupNames,RootNode);
375  // Open a stream to the saving file
376  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
377  Resource::FileStream SettingsStream(FileName,Path,Resource::SF_Truncate | Resource::SF_Write);
378  SettingsDoc.Save(SettingsStream,"\t",XML::FormatIndent);
379  }else{
380  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,"Failed to create XML document declaration for file \"" + FileName + "\".");
381  }
382  }
383 
385  {
386  for( XML::AttributeIterator SettingIt = XMLNode.attributes_begin() ; SettingIt != XMLNode.attributes_end() ; ++SettingIt )
387  {
388  XML::Attribute CurrAttrib = (*SettingIt);
389  if( !CurrAttrib.Empty() )
390  Set->SetSettingValue(CurrAttrib.Name(),CurrAttrib.AsString());
391  }
392  for( XML::NodeIterator SubSetIt = XMLNode.begin() ; SubSetIt != XMLNode.end() ; ++SubSetIt )
393  {
394  XML::Node SubSetNode = (*SubSetIt);
395  ObjectSettingSet* NewSubSet = Set->CreateChildObjectSettingSet( SubSetNode.Name() );
396  this->LoadSettingSetFromXML( SubSetNode, NewSubSet );
397  }
398  }
399 
401  {
402  for( ObjectSettingSet::SettingsIterator SetIt = Set->SettingsBegin() ; SetIt != Set->SettingsEnd() ; ++SetIt )
403  {
404  XML::Attribute CurrAttrib = XMLNode.AppendAttribute( (*SetIt).first );
405  CurrAttrib.SetValue( (*SetIt).second );
406  }
407  for( ObjectSettingSetContainer::SubSetIterator SubSetIt = Set->SubSetBegin() ; SubSetIt != Set->SubSetEnd() ; ++SubSetIt )
408  {
409  XML::Node SubSetNode = XMLNode.AppendChild( (*SubSetIt)->GetName() );
410  this->SaveSettingSetToXML( SubSetNode, (*SubSetIt) );
411  }
412  }
413 
414  ///////////////////////////////////////////////////////////////////////////////
415  // Setting Group Handling
416 
418  {
419  SettingGroupIterator SetIt = this->SettingGroups.find(GroupName);
420  if( SetIt != this->SettingGroups.end() ) {
421  this->ApplySettingGroupImpl( (*SetIt).second );
422  }else{
423  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,"Setting Group \"" + GroupName + "\" not found when attempting to apply settings.");
424  }
425  }
426 
428  {
429  ObjectSettingGroup* NewGroup = new ObjectSettingGroup(Name);
430  this->SettingGroups.insert( std::pair<String,ObjectSettingGroup*>(Name,NewGroup) );
431  return NewGroup;
432  }
433 
435  {
436  ConstSettingGroupIterator SetIt = this->SettingGroups.find(Name);
437  if( SetIt != this->SettingGroups.end() ) return (*SetIt).second;
438  else return NULL;
439  }
440 
442  {
443  SettingGroupIterator SetIt = this->SettingGroups.find(Name);
444  if( SetIt != this->SettingGroups.end() ) {
445  delete (*SetIt).second;
446  this->SettingGroups.erase(SetIt);
447  }
448  }
449 
451  {
452  this->DestroySettingGroup( ToBeDestroyed->GetName() );
453  }
454 
456  {
457  for( SettingGroupIterator SetIt = this->SettingGroups.begin() ; SetIt != this->SettingGroups.end() ; ++SetIt )
458  {
459  delete (*SetIt).second;
460  }
461  this->SettingGroups.clear();
462  }
463 
464  ///////////////////////////////////////////////////////////////////////////////
465  // Setting File Handling
466 
468  {
469  ObjectSettingFile* NewFile = new ObjectSettingFile(FileName);
470  this->SettingFiles.insert( std::pair<String,ObjectSettingFile*>(FileName,NewFile) );
471  return NewFile;
472  }
473 
475  {
476  SettingFilesIterator SettingFileIt = this->SettingFiles.find(FileName);
477  if( SettingFileIt != this->SettingFiles.end() ) return (*SettingFileIt).second;
478  else return NULL;
479  }
480 
482  {
483  SettingFilesIterator SettingFileIt = this->SettingFiles.find(FileName);
484  if( SettingFileIt != this->SettingFiles.end() )
485  {
486  ObjectSettingFile* ToDestroy = (*SettingFileIt).second;
487  delete ToDestroy;
488  this->SettingFiles.erase(SettingFileIt);
489  }
490  }
491 
493  {
494  this->DestroySettingFile( ToBeDestroyed->GetFileName() );
495  }
496 
498  {
499  ObjectSettingFile* ToDestroy = NULL;
500  for( SettingFilesIterator SettingFileIt = this->SettingFiles.begin() ; SettingFileIt != this->SettingFiles.end() ; ++SettingFileIt )
501  {
502  ToDestroy = (*SettingFileIt).second;
503  delete ToDestroy;
504  }
505  this->SettingFiles.clear();
506  }
507 
509  {
510  ObjectSettingFile* GroupFile = NULL;
511  if( FileName.empty() )
512  return;
513 
514  SettingFilesIterator SettingFileIt = this->SettingFiles.find(FileName);
515  if( SettingFileIt != this->SettingFiles.end() ) GroupFile = (*SettingFileIt).second;
516  else
517  {
518  GroupFile = new ObjectSettingFile(FileName);
519  this->SettingFiles.insert( std::pair<String,ObjectSettingFile*>(FileName,GroupFile) );
520  }
521 
522  GroupFile->AddGroup(Group);
523  }
524 
525  void ObjectSettingsHandler::RemoveGroupFromFile(ObjectSettingGroup* Group, const String& FileName)
526  {
527  if( FileName.empty() )
528  return;
529 
530  SettingFilesIterator SettingFileIt = this->SettingFiles.find(FileName);
531  if( SettingFileIt != this->SettingFiles.end() ) (*SettingFileIt).second->RemoveGroup(Group);
532  else return;
533  }
534 
535  ///////////////////////////////////////////////////////////////////////////////
536  // Setting Path Handling
537 
538  void ObjectSettingsHandler::SetSettingsFilePath(const String& Path)
539  {
540  size_t FirstDol = Path.find_first_of('$');
541  size_t SecondDol = Path.find_first_of('$',FirstDol+1);
542  if(FirstDol != String::npos && SecondDol != String::npos) {
543  String PathKeyWord = Path.substr( FirstDol + 1, ( SecondDol - FirstDol ) - 1 );
544  String RestOfPath = Path.substr( SecondDol + 1 );
545  String ActualPath = Resource::ResolveDataPathFromString(PathKeyWord);
546  this->SettingsFilePath = ActualPath + RestOfPath;
547  }else{
548  this->SettingsFilePath = Path;
549  }
550 
551  if( this->AutoGenPath )
552  Resource::CreateDirectoryPath(this->SettingsFilePath);
553  }
554 
555  const String& ObjectSettingsHandler::GetSettingsFilePath() const
556  {
557  return this->SettingsFilePath;
558  }
559 
560  void ObjectSettingsHandler::SetCurrentSettingsSaveFile(const String& FileName)
561  {
562  this->CurrentSettingsSaveFile = FileName;
563  }
564 
565  ConstString& ObjectSettingsHandler::GetCurrentSettingsSaveFile() const
566  {
567  return this->CurrentSettingsSaveFile;
568  }
569 
570  ///////////////////////////////////////////////////////////////////////////////
571  // Loading Utilities
572 
573  CountedPtr<ObjectSettingsHandler::SettingGroupVector> ObjectSettingsHandler::LoadSettingsFromGroup(const String& FileName, const String& Group)
574  {
575  String FilePath = Resource::ResourceManager::GetSingletonPtr()->GetAssetPath(FileName,Group);
576  if( FilePath.empty() ) {
577  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Failed to find path for file \"" + FileName + "\", in group \"" + Group + "\".");
578  }
579  return this->LoadSettingsFromFile(FileName,FilePath);
580  }
581 
582  CountedPtr<ObjectSettingsHandler::SettingGroupVector> ObjectSettingsHandler::LoadSettings(const String& FileName, const String& Path)
583  {
584  return this->LoadSettingsFromFile(FileName,Path);
585  }
586 
587  CountedPtr<ObjectSettingsHandler::SettingGroupVector> ObjectSettingsHandler::LoadSettings(const String& FileName)
588  {
589  if( this->SettingsFilePath.empty() ) {
590  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to use a preset path that hasn't been set.");
591  }
592  return this->LoadSettingsFromFile(FileName,this->SettingsFilePath);
593  }
594 
595  CountedPtr<ObjectSettingsHandler::SettingGroupVector> ObjectSettingsHandler::LoadSettingsFromXML(XML::Node& RootSettings)
596  {
597  ObjectSettingGroup* SetAfter = NULL;
599  for( XML::NodeIterator CurrGroupIt = RootSettings.begin() ; CurrGroupIt != RootSettings.end() ; ++CurrGroupIt )
600  {
601  XML::Node CurrGroupNode = (*CurrGroupIt);
602  String SettingGroupName = CurrGroupNode.Name();
603  ObjectSettingGroup* NewGroup = new ObjectSettingGroup(SettingGroupName);
604  if( "Current" != SettingGroupName ) {
605  this->SettingGroups.insert( std::pair<String,ObjectSettingGroup*>(SettingGroupName,NewGroup) );
606  RetVec->push_back(NewGroup);
607  }else{
608  if(!SetAfter) SetAfter = NewGroup;
609  else { MEZZ_EXCEPTION(ExceptionBase::II_DUPLICATE_IDENTITY_EXCEPTION,"Multiple \"Current\" setting groups detected while loading settings."); }
610  }
611  for( XML::NodeIterator CurrSetIt = CurrGroupNode.begin() ; CurrSetIt != CurrGroupNode.end() ; ++CurrSetIt )
612  {
613  XML::Node CurrSetNode = (*CurrSetIt);
614  String SettingSetName = CurrSetNode.Name();
615  ObjectSettingSet* NewSet = NewGroup->CreateChildObjectSettingSet(SettingSetName);
616  this->LoadSettingSetFromXML( CurrSetNode, NewSet );
617  }
618  }
619  if(SetAfter) {
620  this->ApplySettingGroupImpl(SetAfter);
621  delete SetAfter;
622  }
623  return RetVec;
624  }
625 
626  ///////////////////////////////////////////////////////////////////////////////
627  // Saving Utilities
628 
629  void ObjectSettingsHandler::SetAutoGenPath(Boole Enable)
630  { this->AutoGenPath = Enable; }
631 
632  Boole ObjectSettingsHandler::GetAutoGenPath() const
633  { return this->AutoGenPath; }
634 
635  void ObjectSettingsHandler::SetAutoGenFiles(Boole Enable)
636  { this->AutoGenFiles = Enable; }
637 
638  Boole ObjectSettingsHandler::GetAutoGenFiles() const
639  { return this->AutoGenFiles; }
640 
641  void ObjectSettingsHandler::SaveAllSettings()
642  {
643  if( this->SettingsFilePath.empty() ) {
644  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to use a preset path that hasn't been set.");
645  }
646 
647  StringVector GroupNames;
648  for( SettingFilesIterator SettingFileIt = this->SettingFiles.begin() ; SettingFileIt != this->SettingFiles.end() ; ++SettingFileIt )
649  {
650  ObjectSettingFile* CurrFile = (*SettingFileIt).second;
651  Boole IsCurrentSettingsFile = ( CurrentSettingsSaveFile == CurrFile->GetFileName() );
652  if( CurrFile->GetNeedsSave() || IsCurrentSettingsFile ) {
653  if( IsCurrentSettingsFile )
654  GroupNames.push_back( "Current" );
655  for( ObjectSettingFile::SaveGroupsIterator SetGroupIt = CurrFile->SaveGroupsBegin() ; SetGroupIt != CurrFile->SaveGroupsEnd() ; ++SetGroupIt )
656  {
657  GroupNames.push_back( (*SetGroupIt)->GetName() );
658  }
659  this->SaveSettingsToFile(GroupNames,(*SettingFileIt).second->GetFileName(),SettingsFilePath);
660 
661  CurrFile->SetNeedsSave(false);
662  GroupNames.clear();
663  }
664  }
665  }
666 
667  void ObjectSettingsHandler::SaveSettingsByFile(const String& FileName, const String& Path)
668  {
669  StringVector GroupNames;
670  if( this->CurrentSettingsSaveFile == FileName )
671  GroupNames.push_back( "Current" );
672 
673  SettingFilesIterator SetFileIt = this->SettingFiles.find(FileName);
674  if( SetFileIt == this->SettingFiles.end() ) {
675  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Setting file \"" + FileName + "\" was not found when attempting to save.");
676  }
677 
678  for( ObjectSettingFile::SaveGroupsIterator SetGroupIt = (*SetFileIt).second->SaveGroupsBegin() ; SetGroupIt != (*SetFileIt).second->SaveGroupsEnd() ; ++SetGroupIt )
679  {
680  GroupNames.push_back( (*SetGroupIt)->GetName() );
681  }
682  this->SaveSettingsToFile(GroupNames,FileName,Path);
683  (*SetFileIt).second->SetNeedsSave(false);
684  }
685 
686  void ObjectSettingsHandler::SaveSettingsByFile(const String& FileName)
687  {
688  if( this->SettingsFilePath.empty() ) {
689  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to use a preset path that hasn't been set.");
690  }
691 
692  StringVector GroupNames;
693  if( this->CurrentSettingsSaveFile == FileName )
694  GroupNames.push_back( "Current" );
695 
696  SettingFilesIterator SetFileIt = this->SettingFiles.find(FileName);
697  if( SetFileIt == this->SettingFiles.end() ) {
698  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Setting file \"" + FileName + "\" was not found when attempting to save.");
699  }
700 
701  for( ObjectSettingFile::SaveGroupsIterator SetGroupIt = (*SetFileIt).second->SaveGroupsBegin() ; SetGroupIt != (*SetFileIt).second->SaveGroupsEnd() ; ++SetGroupIt )
702  {
703  GroupNames.push_back( (*SetGroupIt)->GetName() );
704  }
705  this->SaveSettingsToFile(GroupNames,FileName,SettingsFilePath);
706  (*SetFileIt).second->SetNeedsSave(false);
707  }
708 
709  void ObjectSettingsHandler::SaveSettingGroups(StringVector& GroupNames, const String& FileName, const String& Path)
710  {
711  this->SaveSettingsToFile(GroupNames,FileName,Path);
712  }
713 
714  void ObjectSettingsHandler::SaveSettingGroups(StringVector& GroupNames, const String& FileName)
715  {
716  if( this->SettingsFilePath.empty() ) {
717  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to use a preset path that hasn't been set.");
718  }
719 
720  this->SaveSettingsToFile(GroupNames,FileName,SettingsFilePath);
721  }
722 
723  void ObjectSettingsHandler::SaveSettingsToXML(XML::Node& RootSettings, Boole SaveCurrent)
724  {
725  StringVector GroupNames;
726 
727  if(SaveCurrent)
728  GroupNames.push_back( "Current" );
729 
730  for( SettingGroupIterator GroupNameIt = this->SettingGroups.begin() ; GroupNameIt != this->SettingGroups.end() ; ++GroupNameIt )
731  {
732  GroupNames.push_back( (*GroupNameIt).first );
733  }
734  this->SaveSettingsToXML(GroupNames,RootSettings);
735  }
736 
737  void ObjectSettingsHandler::SaveSettingsToXML(StringVector& GroupNames, XML::Node& RootSettings)
738  {
739  for( StringVector::iterator StrIt = GroupNames.begin() ; StrIt != GroupNames.end() ; ++StrIt )
740  {
741  if( "Current" == (*StrIt) ) {
742  this->AppendCurrentSettings(RootSettings);
743  }else{
744  SettingGroupIterator GroupIt = this->SettingGroups.find( (*StrIt) );
745  if( GroupIt == this->SettingGroups.end() ) {
746  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to save setting group \"" + (*StrIt) + "\", which does not exist.");
747  }
748  ObjectSettingSetContainer* SaveSet = (*GroupIt).second;
749  XML::Node GroupNode = RootSettings.AppendChild( (*GroupIt).first );
750  for( ObjectSettingSetContainer::SubSetIterator SubSetIt = SaveSet->SubSetBegin() ; SubSetIt != SaveSet->SubSetEnd() ; ++SubSetIt )
751  {
752  XML::Node SetNode = GroupNode.AppendChild( (*SubSetIt)->GetName() );
753  this->SaveSettingSetToXML( SetNode, (*SubSetIt) );
754  }
755  }
756  }
757  }
758 
759  ///////////////////////////////////////////////////////////////////////////////
760  // Serialization
761 
762  void ObjectSettingsHandler::ProtoSerialize(XML::Node& SelfRoot) const
763  {
764  /// @todo Add more checks to verify successful appending.
765  XML::Node AutoGenNode = SelfRoot.AppendChild("AutoCreateSettings");
766  AutoGenNode.AppendAttribute("Path").SetValue( this->AutoGenPath );
767  AutoGenNode.AppendAttribute("Files").SetValue( this->AutoGenFiles );
768 
769  XML::Node PathNode = SelfRoot.AppendChild("SettingsPath");
770  PathNode.AppendAttribute("Path").SetValue( this->SettingsFilePath );
771 
772  XML::Node FilesNode = SelfRoot.AppendChild("SettingsFiles");
773  for( ConstSettingFilesIterator FileIt = this->SettingFiles.begin() ; FileIt != this->SettingFiles.end() ; ++FileIt )
774  {
775  XML::Node FileNode = FilesNode.AppendChild("SettingsFile");
776  FileNode.AppendAttribute("FileName").SetValue( (*FileIt).second->GetFileName() );
777  /// @todo Add serialization and methods for serializing the group or path.
778  }
779  }
780 
781  void ObjectSettingsHandler::ProtoDeSerialize(const XML::Node& SelfRoot)
782  {
783  XML::Attribute CurrAttrib;
784  String PathPreset;
785  // Get whether or not to autogen the directory path and settings file.
786  XML::Node AutoGenNode = SelfRoot.GetChild("AutoCreateSettings");
787  if( !AutoGenNode.Empty() ) {
788  CurrAttrib = AutoGenNode.GetAttribute("Path");
789  if(!CurrAttrib.Empty()) {
790  this->AutoGenPath = StringTools::ConvertToBool( CurrAttrib.AsString() );
791  }
792  CurrAttrib = AutoGenNode.GetAttribute("Files");
793  if(!CurrAttrib.Empty()) {
794  this->AutoGenFiles = StringTools::ConvertToBool( CurrAttrib.AsString() );
795  }
796  }
797  // Get preset path to default to if a path is not provided.
798  XML::Node PathNode = SelfRoot.GetChild("SettingsPath");
799  if( !PathNode.Empty() ) {
800  CurrAttrib = PathNode.GetAttribute("Path");
801  if( !CurrAttrib.Empty() ) {
802  PathPreset = CurrAttrib.AsString();
803  }
804 
805  if( !PathPreset.empty() ) {
806  this->SetSettingsFilePath(PathPreset);
807  }
808  }
809  // Get the files to be loaded, and load them.
810  XML::Node FilesNode = SelfRoot.GetChild("SettingsFiles");
811  if( !FilesNode.Empty() ) {
812  for( XML::NodeIterator SetFileIt = FilesNode.begin() ; SetFileIt != FilesNode.end() ; ++SetFileIt )
813  {
814  String FileName, FilePath, FileGroup;
815  // Get the filename to load
816  CurrAttrib = (*SetFileIt).GetAttribute("FileName");
817  if( !CurrAttrib.Empty() ) {
818  FileName = CurrAttrib.AsString();
819  }
820  // Get the path
821  CurrAttrib = (*SetFileIt).GetAttribute("Path");
822  if( !CurrAttrib.Empty() ) {
823  FilePath = CurrAttrib.AsString();
824  }else{
825  CurrAttrib = (*SetFileIt).GetAttribute("Group");
826  if( !CurrAttrib.Empty() ) {
827  FileGroup = CurrAttrib.AsString();
828  }
829  }
830 
831  if( FilePath.empty() ) {
832  if(FileGroup.empty()) this->LoadSettings(FileName);
833  else this->LoadSettingsFromGroup(FileName,FileGroup);
834  }else{
835  this->LoadSettings(FileName,FilePath);
836  }
837  }
838  }
839  }
840 
841  String ObjectSettingsHandler::GetSerializableName()
842  { return "ObjectSettingsHandler"; }
843 }
844 
845 #endif
846 
void ApplySettingGroup(const String &GroupName)
Applies all the settings (and their values) defined in a setting group.
~ObjectSettingFile()
Class destructor.
Attribute AppendAttribute(const Char8 *Name)
Creates an Attribute and puts it at the end of this Nodes attributes.
Thrown when duplicates of teh same identity string exist.
Definition: exception.h:95
ConstString & GetName() const
Gets the name of this container.
Boole GetNeedsSave() const
Gets whether or not this file has been updated and needs to be saved.
A light-weight handle for manipulating attributes in DOM tree.
Definition: attribute.h:74
std::vector< String > StringVector
This is a simple datatype for a vector container of strings.
Definition: datatypes.h:212
SettingFilesContainer::const_iterator ConstSettingFilesIterator
Const Iterator type for ObjectSettingGroup instances stored by this class.
attribute_iterator attributes_end() const
Get an Attribute iterator that references the one past the last Attribute on this Node...
ObjectSettingSetContainer * ParentSetOrGroup
A pointer to the parent container of this ObjectSettingSet.
const String & GetOptionalFileName() const
Gets the file name this group will be saved to.
ObjectSettingFile * CreateSettingFile(const String &FileName)
Creates a new Setting file that will track which groups are a part of it.
virtual String GetObjectRootNodeName() const =0
Gets the name to be given to a Node with this handlers serialized data.
ObjectSettingGroup(const String &Name)
Class constructor.
Clear the contents of the file when opening. Note that this will also create the file if it's not fou...
Definition: datastream.h:73
SettingFilesContainer SettingFiles
A container storing all the file saving configuration used by this handler.
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
SubSetVector::const_iterator ConstSubSetIterator
Const Iterator type for ObjectSettingSet instances stored by this class.
SubSetVector::iterator SubSetIterator
Iterator type for ObjectSettingSet instances stored by this class.
void _SetOptionalFile(ObjectSettingFile *File)
Sets the file this group will be saved to.
SaveGroupsContainer & GetGroups()
Gets the container with the groups to be saved to this file.
ObjectSettingFile(const String &FileName)
Class constructor.
attribute_iterator attributes_begin() const
Get an Attribute iterator that references the first Attribute on this Node.
void LoadSettingSetFromXML(XML::Node &XMLNode, ObjectSettingSet *Set)
Populates an ObjectSettingSet with settings stored in XML.
SaveGroupsContainer::const_iterator ConstSaveGroupsIterator
Const Iterator type for ObjectSettingGroup instances stored by this class.
Thrown when the requested identity could not be found.
Definition: exception.h:94
Thrown when a file was expected to be there, but was not.
Definition: exception.h:467
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
A class that store's a named set of settings for an object.
A simple reference counting pointer.
Definition: countedptr.h:70
Declaration of FileStream.
void DestroyAllObjectSettingSets()
Destroys all child Sub-Sets of this container.
String File
The name of the file the stored ObjectSettingGroup instances will be saved to.
const Char8 * AsString(const Char8 *def="") const
Attempts to convert the value of the attribute to a String and returns the results.
void SetSettingValue(const String &SettingName, const String &StringValue)
Sets a setting in this set...of settings.
SaveGroupsIterator SaveGroupsEnd()
Gets an iterator to one-passed the last group in this file.
ObjectSettingGroup * CreateSettingGroup(const String &Name)
Creates a new blank setting group that can have it's settings populated.
void AddGroup(ObjectSettingGroup *Group)
Adds a group to be saved to this file.
SettingsIterator SettingsEnd()
Gets an iterator to one passed the last setting in this set.
ObjectSettingFile * GetSettingFile(const String &FileName)
Gets a Setting file by name.
void DestroyAllSettingGroups()
Destroys all setting groups stored in this handler.
bool Empty() const
Is this storing anything at all?
SubSetIterator SubSetEnd()
Gets an iterator to one passed the last subset of settings in this set.
ParseResult Load(std::basic_istream< char, std::char_traits< char > > &stream, unsigned int options=ParseDefault, Encoding DocumentEncoding=EncodingAuto)
Load XML from a stream.
const String Blank
Convenience String for comparing to return blank Strings where necessary.
Definition: stringtool.h:64
virtual ~ObjectSettingSetContainer()
Class destructor.
virtual ~ObjectSettingSet()
Class destructor.
ObjectSettingGroup * GetSettingGroup(const String &Name) const
Gets a setting group by name.
ObjectSettingsHandler()
Class constructor.
SettingGroupContainer::const_iterator ConstSettingGroupIterator
Const Iterator type for ObjectSettingGroup instances stored by this class.
virtual void RemoveChildObjectSettingSet(ObjectSettingSet *ToBeRemoved)
Removes a Sub-Set of this container.
This class represents a file to be saved containing one or more OhjectSettingGroup's.
void DestroyAllSettingFiles()
Destroys all Setting files in this handler.
void Save(Writer &WriterInstance, const Char8 *indent="\t", unsigned int flags=FormatDefault, Encoding DocumentEncoding=EncodingAuto) const
Save XML document to WriterInstance.
bool SetValue(const Char8 *rhs)
Set the value of this.
uint16_t UInt16
An 16-bit unsigned integer.
Definition: datatypes.h:122
bool SetName(const Char8 *rhs)
Set the name of .
ObjectSettingSetContainer * GetParentSetOrGroup() const
Gets the Parent SettingsSet to this set.
CountedPtr< SettingGroupVector > LoadSettingsFromFile(const String &FileName, const String &Path)
Loads all ObjectSettingGroup instances serialized to a XML file into usable ObjectSettingGroup instan...
virtual void AddChildObjectSettingSet(ObjectSettingSet *ToBeAdded)
Adds a SettingSet as a child of this container.
Permit write operations on the stream.
Definition: datastream.h:69
Child node iterator (a bidirectional iterator over a collection of Node)
Definition: nodeiterator.h:77
void SaveSettingSetToXML(XML::Node &XMLNode, ObjectSettingSet *Set)
Saves an ObjectSettingSet to an XML node.
void _MarkUpdated()
Marks this container and relevant parent containers as updated.
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
iterator begin() const
Get a Child node iterator that references the first child Node.
const String ConstString
A Datatype used to a series of imutable characters.
Definition: datatypes.h:165
void SaveSettingsToXML(XML::Node &RootSettings, Boole SaveCurrent=true)
Saves all the current setting groups as children of the provided XML node.
void SetName(const String &Name)
Sets the name of this container.
String GetSettingValue(const String &SettingName) const
Gets a String representing the Value currently assigned to the existing setting.
iterator end() const
Get a Child node iterator that references one past the last child Node.
bool Empty() const
Is this storing anything at all?
ObjectSettingSetContainer(const String &Name)
Class constructor.
ObjectSettingFile * GetOptionalFile() const
Gets the Setting file instance this group will be saved to.
Boole NeedsSave
Stores whether or not the settings have been updated and this file needs to be saved/refreshed.
SubSetVector SubSets
A container of ObjectSettingSet instances owned by this container.
The defintion of the Resource Manager.
void _MarkUpdated()
Marks this container and relevant parent containers as updated.
SubSetIterator SubSetBegin()
Gets an iterator to the first subset of settings in this set.
std::vector< ObjectSettingGroup * > SaveGroupsContainer
Basic container type for ObjectSettingGroup storage by this class.
SaveGroupsIterator SaveGroupsBegin()
Gets an iterator to the first group in this file.
void DestroyChildObjectSettingSet(const String &Name)
Destroys a Sub-Set of this container.
ObjectSettingSet * GetChildObjectSettingSet(const String &Name, UInt16 Which=0) const
Gets a Sub-Set of this container by name.
virtual ObjectSettingSet * CreateChildObjectSettingSet(const String &Name)
Creates a new SettingSet as a child of this container.
virtual void _MarkUpdated()=0
Marks this container and relevant parent containers as updated.
Thrown when the available information should have worked but failed for unknown reasons.
Definition: exception.h:113
SettingGroupContainer::iterator SettingGroupIterator
Iterator type for ObjectSettingGroup instances stored by this class.
Attribute iterator (a bidirectional iterator over a collection of Attribute).
CountedPtr< SettingGroupVector > LoadSettingsFromXML(XML::Node &RootSettings)
Loads settings from an xml node.
The root node of any xml hierarchy is a Document.
Definition: document.h:83
void AddGroupToFile(ObjectSettingGroup *Group, const String &FileName)
Assigns a SettingGroup to a file name that will be used when settings are saved.
const Char8 * Name() const
Get the name of this Attribute.
Thrown when the identity string wasn't valid at all.
Definition: exception.h:93
ObjectSettingSet(const String &Name)
Class constructor.
Document declaration, i.e. ''.
ObjectSettingGroup * GetGroup(const String &Name) const
Gets a group being saved to this file.
void SaveSettingsToFile(StringVector &GroupNames, const String &FileName, const String &Path)
Saves a collection of ObjectSettingGroups stored by this handler to a file as XML.
This represents a stream to a file on disk using the C++ file stream API.
Definition: filestream.h:56
virtual void ApplySettingGroupImpl(ObjectSettingGroup *Group)=0
Applies all the settings stored by a ObjectSettingGroup.
A base class for other classes that store ObjectSettingSet's.
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
ObjectSettingFile * OptionalFile
A pointer to the ObjectSettingFile instance this setting group will be saved to.
void DestroySettingFile(const String &FileName)
Destroys a Setting file by name.
SaveGroupsContainer SaveGroups
A container of ObjectSettingGroup instances that will be saved to the file representing by this...
virtual ~ObjectSettingGroup()
Class destructor.
void RemoveGroup(ObjectSettingGroup *Group)
Removes a group from this file.
SettingFilesContainer::iterator SettingFilesIterator
Iterator type for ObjectSettingGroup instances stored by this class.
SettingsMap::const_iterator ConstSettingsIterator
Const Iterator type for settings stored by this class.
const Char8 * Name() const
ptrdiff_tGet the name of this Node.
const String & GetFileName() const
Gets the name of the file.
SettingGroupContainer SettingGroups
A container storing all the SettingGroups owned by this handler.
void SetNeedsSave(Boole Save)
Sets whether or not this file needs saving.
String CurrentSettingsSaveFile
Stores the name of the file where the "Current" settings group will be saved to.
SaveGroupsContainer::iterator SaveGroupsIterator
Iterator type for ObjectSettingGroup instances stored by this class.
std::vector< ObjectSettingGroup * > SettingGroupVector
Convenience typedef for Load method returns.
virtual ~ObjectSettingsHandler()
Class destructor.
Node AppendChild(NodeType Type=NodeElement)
Creates a Node and makes it a child of this one.
A class that store's a collection of SettingSets that can be applied together.
SettingsMap::iterator SettingsIterator
Iterator type for settings stored by this class.
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
void DestroySettingGroup(const String &Name)
Destroys a setting group by name.
String ContainerName
The name of this container.
Attribute GetAttribute(const Char8 *Name) const
Attempt to get an Attribute on this Node with a given name.
Node GetChild(const Char8 *Name) const
Attempt to get a child Node with a given name.
SettingsMap Settings
A map container storing the settings owned by this set and their values.
SettingsIterator SettingsBegin()
Gets an iterator to the first setting in this set.
const unsigned int FormatIndent
Indent the nodes that are written to output stream with as many indentation strings as deep the node ...