Imported Upstream version 1.2.99~20120606~SE~ff65aef~SYSYNC~2728cb4
[platform/upstream/syncevolution.git] / src / syncevo / ConfigFilter.cpp
1 /*
2  * Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
3  * Copyright (C) 2009 Intel Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) version 3.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301  USA
19  */
20
21 #include "config.h"
22
23 #include <syncevo/ConfigFilter.h>
24 #include <syncevo/SyncConfig.h>
25
26 using namespace std;
27
28 SE_BEGIN_CXX
29
30 void ConfigProps::add(const ConfigProps &other)
31 {
32     BOOST_FOREACH(const ConfigProps::value_type &entry, other) {
33         std::pair<iterator, bool> res = insert(entry);
34         if (!res.second) {
35             res.first->second = entry.second;
36         }
37     }
38 }
39
40 InitStateString ConfigProps::get(const string &key, const string &def) const
41 {
42     const_iterator it = find(key);
43     if (it == end()) {
44         return InitStateString(def, false);
45     } else {
46         return it->second;
47     }
48 }
49
50 ConfigProps::operator string () const
51 {
52     vector<string> res;
53     BOOST_FOREACH(const StringPair &filter, *this) {
54         res.push_back(filter.first + " = " + filter.second);
55     }
56     sort(res.begin(), res.end());
57     return boost::join(res, "\n");
58 }
59
60 ConfigProps SourceProps::createSourceFilter(const std::string &source) const
61 {
62     const_iterator it = find("");
63     ConfigProps filter;
64     if (it != end()) {
65         filter = it->second;
66     }
67     if (!source.empty()) {
68         it = find(source);
69         if (it != end()) {
70             filter.add(it->second);
71         }
72     }
73     return filter;
74 }
75
76 ConfigProps FullProps::createSyncFilter(const std::string &config) const
77 {
78     const_iterator it = find("");
79     ConfigProps filter;
80     if (it != end()) {
81         // first unset context
82         filter = it->second.m_syncProps;
83     }
84
85     if (!config.empty()) {
86         std::string normal = SyncConfig::normalizeConfigString(config, SyncConfig::NORMALIZE_LONG_FORMAT);
87         std::string peer, context;
88         SyncConfig::splitConfigString(normal, peer, context);
89         // then overwrite with context config
90         it = find(std::string("@") + context);
91         if (it != end()) {
92             filter.add(it->second.m_syncProps);
93         }
94         // finally peer config, if we have one
95         if (!peer.empty()) {
96             it = find(normal);
97             if (it != end()) {
98                 filter.add(it->second.m_syncProps);
99             }
100         }
101     }
102     return filter;
103 }
104
105 ConfigProps FullProps::createSourceFilter(const std::string &config,
106                                           const std::string &source) const
107 {
108     const_iterator it = find("");
109     ConfigProps filter;
110     if (it != end()) {
111         // first unset context
112         filter = it->second.m_sourceProps.createSourceFilter(source);
113     }
114
115     if (!config.empty()) {
116         std::string normal = SyncConfig::normalizeConfigString(config, SyncConfig::NORMALIZE_LONG_FORMAT);
117         std::string peer, context;
118         SyncConfig::splitConfigString(normal, peer, context);
119         // then overwrite with context config
120         it = find(std::string("@") + context);
121         if (it != end()) {
122             filter.add(it->second.m_sourceProps.createSourceFilter(source));
123         }
124         // finally peer config, if we have one
125         if (!peer.empty()) {
126             it = find(normal);
127             if (it != end()) {
128                 filter.add(it->second.m_sourceProps.createSourceFilter(source));
129             }
130         }
131     }
132     return filter;
133 }
134
135 bool FullProps::hasProperties(PropCheckMode mode) const
136 {
137     BOOST_FOREACH(const value_type &context, *this) {
138         if (mode == CHECK_ALL &&
139             !context.second.m_syncProps.empty()) {
140             return true;
141         }
142         if (mode == IGNORE_GLOBAL_PROPS) {
143             const ConfigPropertyRegistry &registry = SyncConfig::getRegistry();
144             BOOST_FOREACH(const StringPair &entry, context.second.m_syncProps) {
145                 const ConfigProperty *prop = registry.find(entry.first);
146                 if (!prop ||
147                     prop->getSharing() != ConfigProperty::GLOBAL_SHARING) {
148                     return true;
149                 }
150             }
151         }
152         BOOST_FOREACH(const SourceProps::value_type &source, context.second.m_sourceProps) {
153             if (!source.second.empty()) {
154                 return true;
155             }
156         }
157     }
158
159     return false;
160 }
161
162 void FullProps::createFilters(const string &context,
163                               const string &config,
164                               const set<string> *sources,
165                               ConfigProps &syncFilter,
166                               SourceProps &sourceFilters)
167 {
168     boost::shared_ptr<SyncConfig> shared;
169
170     if (!context.empty()) {
171         // Read from context. If it does not exist, we simply set no properties
172         // as filter. Previously there was a check for existance, but that was
173         // flawed because it ignored the global property "defaultPeer".
174         shared.reset(new SyncConfig(context));
175         shared->getProperties()->readProperties(syncFilter);
176     }
177
178     // add command line filters for context or config?
179     if (!context.empty()) {
180         syncFilter.add(createSyncFilter(context));
181         // default for (so far) unknown sources which might be created
182         sourceFilters[""].add(createSourceFilter(context, ""));
183     }
184     if (!config.empty()) {
185         syncFilter.add(createSyncFilter(config));
186         sourceFilters[""].add(createSourceFilter(config, ""));
187     }
188
189     // build full set of all sources
190     set<string> allSources;
191     if (sources) {
192         allSources = *sources;
193     }
194     if (shared) {
195         std::list<std::string> tmp = shared->getSyncSources();
196         allSources.insert(tmp.begin(), tmp.end());
197     }
198     if (!config.empty()) {
199         std::list<std::string> tmp = SyncConfig(config).getSyncSources();
200         allSources.insert(tmp.begin(), tmp.end());
201     }
202
203     // explicit filter for all known sources
204     BOOST_FOREACH(std::string source, allSources) {
205         ConfigProps &props = sourceFilters[source];
206         if (shared) {
207             // combine existing properties from context and command line
208             // filter
209             SyncSourceNodes nodes = shared->getSyncSourceNodes(source, "");
210             nodes.getProperties()->readProperties(props);
211
212             // Special case "type" property: the value in the context
213             // is not preserved. Every new peer must ensure that
214             // its own value is compatible (= same backend) with
215             // the other peers.
216             props.erase("type");
217
218             props.add(createSourceFilter(context, source));
219         }
220         if (!config.empty()) {
221             props.add(createSourceFilter(config, source));
222         }
223     }
224 }
225
226 SE_END_CXX