]> git.tdb.fi Git - libs/datafile.git/blob - source/collection.cpp
Add an API to open files from a collection's sources
[libs/datafile.git] / source / collection.cpp
1 #include "collection.h"
2
3 using namespace std;
4
5 namespace Msp {
6 namespace DataFile {
7
8 Collection::Collection():
9         fallback(0)
10 { }
11
12 Collection::~Collection()
13 {
14         for(TypeList::iterator i = types.begin(); i!=types.end(); ++i)
15                 delete *i;
16 }
17
18 const Variant &Collection::get_var(const string &name, const CollectionItemTypeBase *type)
19 {
20         ItemMap::iterator i = items.find(name);
21         if(i!=items.end())
22                 return i->second;
23
24         if(type)
25         {
26                 bool loaded = false;
27                 if(type->can_create())
28                 {
29                         type->create_item(*this, name);
30                         loaded = items.count(name);
31                 }
32                 for(SourceList::iterator j=sources.begin(); (!loaded && j!=sources.end()); ++j)
33                 {
34                         (*j)->load(*this, *type, name);
35                         loaded = items.count(name);
36                 }
37                 if(!loaded && fallback)
38                 {
39                         for(TypeList::const_iterator j=fallback->types.begin(); j!=fallback->types.end(); ++j)
40                                 if((*j)->is_same_type(*type))
41                                 {
42                                         if(fallback->get_status(name, **j))
43                                                 return fallback->get_var(name, *j);
44                                         break;
45                                 }
46                 }
47         }
48
49         return get_item(items, name);
50 }
51
52 void Collection::gather_items(list<const Variant *> *vars, list<string> *names, const CollectionItemTypeBase &type, bool include_sources) const
53 {
54         for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i)
55                 if(type.check_item_type(i->second))
56                 {
57                         if(vars)
58                                 vars->push_back(&i->second);
59                         if(names)
60                                 names->push_back(i->first);
61                 }
62
63         if(include_sources && names)
64                 gather_names_from_sources(*names, type);
65 }
66
67 unsigned Collection::get_status(const string &name, const CollectionItemTypeBase &type) const
68 {
69         ItemMap::const_iterator i = items.find(name);
70         if(i==items.end())
71         {
72                 for(SourceList::const_iterator j=sources.begin(); j!=sources.end(); ++j)
73                         if((*j)->is_loadable(type, name))
74                                 return 2;
75                 return 0;
76         }
77
78         return type.check_item_type(i->second);
79 }
80
81 CollectionItemTypeBase *Collection::get_type_for_item(const Variant &var) const
82 {
83         for(TypeList::const_iterator i=types.begin(); i!=types.end(); ++i)
84                 if((*i)->check_item_type(var))
85                         return *i;
86         return 0;
87 }
88
89 void Collection::add_source(CollectionSource &s)
90 {
91         sources.push_back(&s);
92 }
93
94 IO::Seekable *Collection::open_from_sources(const string &name)
95 {
96         for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
97                 if(IO::Seekable *io = (*i)->open(name))
98                         return io;
99
100         throw IO::file_not_found(name);
101 }
102
103 void Collection::gather_names_from_sources(list<string> &names, const CollectionItemTypeBase &type) const
104 {
105         for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
106         {
107                 std::list<std::string> available_names = (*i)->get_names(type);
108                 for(std::list<std::string>::iterator j=available_names.begin(); j!=available_names.end(); ++j)
109                         if(!items.count(*j))
110                                 names.push_back(*j);
111         }
112 }
113
114 void Collection::load_items_from_sources(const CollectionItemTypeBase &type)
115 {
116         for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
117         {
118                 std::list<std::string> available_names = (*i)->get_names(type);
119                 for(std::list<std::string>::iterator j=available_names.begin(); j!=available_names.end(); ++j)
120                         if(!items.count(*j))
121                                 (*i)->load(*this, type, *j);
122         }
123 }
124
125 void Collection::set_fallback(Collection *f)
126 {
127         fallback = f;
128 }
129
130
131 Collection::Loader::Loader(Collection &c):
132         coll(c)
133 {       
134         for(TypeList::const_iterator i = coll.types.begin(); i!=coll.types.end(); ++i)
135                 (*i)->add_to_loader(*this);
136 }
137
138
139 CollectionItemTypeBase::~CollectionItemTypeBase()
140 {
141         for(vector<ExtractorBase *>::iterator i=extractors.begin(); i!=extractors.end(); ++i)
142                 delete *i;
143 }
144
145 void CollectionItemTypeBase::set_keyword(const string &k)
146 {
147         kwd = k;
148         if(suffixes.empty())
149                 add_suffix("."+kwd);
150 }
151
152 void CollectionItemTypeBase::add_suffix(const string &s)
153 {
154         suffixes.push_back(s);
155 }
156
157 bool CollectionItemTypeBase::match_name(const string &name) const
158 {
159         for(vector<string>::const_iterator i=suffixes.begin(); i!=suffixes.end(); ++i)
160                 if(name.size()>i->size() && !name.compare(name.size()-i->size(), string::npos, *i))
161                         return true;
162         return false;
163 }
164
165 } // namespace DataFile
166 } // namespace Msp