]> git.tdb.fi Git - libs/datafile.git/blob - source/directorycollection.h
Proper loading of collection-enabled objects in DirectoryCollection
[libs/datafile.git] / source / directorycollection.h
1 #ifndef MSP_DATAFILE_DIRECTORYCOLLECTION_H_
2 #define MSP_DATAFILE_DIRECTORYCOLLECTION_H_
3
4 #include <msp/fs/path.h>
5 #include "collection.h"
6
7 namespace Msp {
8 namespace DataFile {
9
10 /**
11 A Collection that can automatically load items from files in a directory.
12 */
13 class DirectoryCollection: public Collection
14 {
15 private:
16         template<typename T, bool = NeedsCollection<typename T::Loader>::value>
17         class ItemLoader;
18
19         std::list<FS::Path> dirs;
20
21 public:
22         DirectoryCollection();
23
24 protected:
25         void set_directory(const FS::Path &);
26         void add_directory(const FS::Path &);
27
28         template<typename T>
29         CollectionItemType<T> &add_type()
30         {
31                 return Collection::add_type<T>().creator(&DirectoryCollection::create<T>);
32         }
33
34 private:
35         template<typename T>
36         T *create(const std::string &name)
37         {
38                 FS::Path file;
39                 if(lookup_file(name, file))
40                 {
41                         RefPtr<T> item = new T;
42                         ItemLoader<T> ldr(*item, *this);
43                         IO::BufferedFile in(file.str());
44                         Parser parser(in, file.str());
45                         ldr.load(parser);
46                         return item.release();
47                 }
48                 else
49                         return 0;
50         }
51
52 protected:
53         bool lookup_file(const std::string &, FS::Path &) const;
54 };
55
56 template<typename T>
57 class DirectoryCollection::ItemLoader<T, false>: public T::Loader
58 {
59 public:
60         ItemLoader(T &o, Collection &):
61                 T::Loader(o)
62         { }
63 };
64
65 template<typename T>
66 class DirectoryCollection::ItemLoader<T, true>: public T::Loader
67 {
68 public:
69         ItemLoader(T &o, Collection &c):
70                 T::Loader(o, dynamic_cast<typename T::Loader::Collection &>(c))
71         { }
72 };
73
74 } // namespace DataFile
75 } // namespace Msp
76
77 #endif