2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file powder_parser.cpp
18 * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
20 * @brief Parser for WAC defined POWDER
27 #include <dpl/log/log.h>
28 #include <dpl/sstream.h>
29 #include <dpl/foreach.h>
30 #include "powder_parser.h"
31 #include "ignoring_parser.h"
32 #include "deny_all_parser.h"
35 void MergeDescriptions(WrtDB::Powder::Description* dest,
36 const WrtDB::Powder::Description& src)
39 // LogInfo("MergeDescriptions dest: " << *dest <<
41 if (!dest->ageRating) {
42 dest->ageRating = src.ageRating;
44 if (!!src.ageRating) {
45 if (*dest->ageRating > *src.ageRating) {
46 dest->ageRating = src.ageRating;
50 FOREACH(catIter, src.categories)
52 FOREACH(levelIter, catIter->second.levels)
54 dest->categories[catIter->first].levels.push_back(*levelIter);
57 // LogInfo("MergeDescriptions result:" << *dest);
60 //TODO::Check if list of delimiters is valid
61 const DPL::String constPowderDelimiters = DPL::FromUTF32String(L" ,;\n\r\t");
62 } //anonymous namespace
64 std::ostream & operator<<(std::ostream& aStream,
65 const StringSet& aContainer)
67 if (!aContainer.empty()) {
68 StringSet::const_iterator iter = aContainer.begin();
69 aStream << "{[" << *iter;
71 for (/*empty*/; iter != aContainer.end(); ++iter) {
72 aStream << "] [" << *iter;
79 #define DEFINE_ELEMENT_FUNC(element, myClass) \
80 m_map[DPL::FromUTF32String(L"" # element)] = \
81 DPL::MakeDelegate(this, &myClass::OnElement_ ## element);
83 class DenyUnknownTagsParser : public ElementParser
86 DenyUnknownTagsParser() : ElementParser()
90 void Accept(const XmlAttribute& /*attribute*/)
94 void Accept(const Element& /*element*/)
98 void Accept(const Text& /*text*/)
102 ElementParserPtr OnDenyElement()
104 return ElementParserPtr(new DenyAllParser());
107 ActionFunc GetElementParser(const DPL::String& /*ns*/,
108 const DPL::String& /*name*/)
110 return DPL::MakeDelegate(this, &DenyUnknownTagsParser::OnDenyElement);
117 StringSet TokenizeTag(const DPL::String& buffer)
120 DPL::Tokenize(buffer, constPowderDelimiters,
121 std::insert_iterator<StringSet>(data, data.begin()), true);
125 class SetOfTextValuesParser : public DenyUnknownTagsParser
128 explicit SetOfTextValuesParser(std::set<DPL::String>* data) :
129 DenyUnknownTagsParser(),
135 virtual void Accept(const Text& text)
138 m_buffer += text.value;
142 *m_data = TokenizeTag(m_buffer);
146 DPL::String m_buffer;
150 // It is data structure used by iriset parser to match IRI's
151 // and preserve processing result
152 struct IrisetParserData
154 const DPL::String* m_host;
155 const DPL::String* m_path;
157 IrisetParserData(const DPL::String& host,
158 const DPL::String& path) :
166 class IrisetParser : public DenyUnknownTagsParser
169 explicit IrisetParser(IrisetParserData* data) :
170 DenyUnknownTagsParser(),
176 DEFINE_ELEMENT_FUNC(includehosts, IrisetParser);
177 DEFINE_ELEMENT_FUNC(includeexactpaths, IrisetParser);
180 ElementParserPtr OnElement_includehosts()
183 return ElementParserPtr(new SetOfTextValuesParser(&m_hosts));
186 ElementParserPtr OnElement_includeexactpaths()
189 return ElementParserPtr(new SetOfTextValuesParser(&m_paths));
194 if (m_hostsDetected <= 1 && m_pathsDetected <= 1) {
195 LogInfo("Matching iriset for host [" <<
196 *m_data->m_host << "] path [" <<
197 *m_data->m_path << "]");
198 LogInfo("hosts: " << m_hosts <<
199 " paths: " << m_paths);
201 m_hosts.find(*m_data->m_host) != m_hosts.end() &&
202 m_paths.find(*m_data->m_path) != m_paths.end();
204 ThrowMsg(PowderParserException::ParserFailed,
205 "Invalid iriset contents");
210 IrisetParserData* m_data;
211 typedef StringSet Container;
214 size_t m_hostsDetected;
215 size_t m_pathsDetected;
218 class WacCategoryParser : public DenyUnknownTagsParser
221 WacCategoryParser(WrtDB::Powder::Description::LevelEntry* data) :
222 DenyUnknownTagsParser(),
228 virtual void Accept(const Text& text)
231 m_buffer += text.value;
234 static StringSet GetAllowedAttributes()
237 allowed.insert(DPL::FromUTF32String(L"xa"));
238 allowed.insert(DPL::FromUTF32String(L"xb"));
239 allowed.insert(DPL::FromUTF32String(L"xc"));
240 allowed.insert(DPL::FromUTF32String(L"xd"));
241 allowed.insert(DPL::FromUTF32String(L"xe"));
245 virtual void Accept(const XmlAttribute& attribute)
247 static StringSet allowed = GetAllowedAttributes();
248 if (allowed.find(attribute.name) != allowed.end()) {
249 if (DPL::FromUTF32String(L"1") == attribute.value) {
250 m_data->context.insert(attribute.name);
251 } else if (DPL::FromUTF32String(L"0") != attribute.value) {
252 ThrowMsg(PowderParserException::ParserFailed,
253 "Invalid attribute for WAC category tag");
256 ThrowMsg(PowderParserException::ParserFailed,
257 "Invalid tag in descriptionset");
261 virtual void Verify()
263 StringSet values = TokenizeTag(m_buffer);
264 bool numberFound = false;
266 FOREACH(wordIter, values) {
267 DPL::IStringStream str(*wordIter);
271 ThrowMsg(PowderParserException::ParserFailed,
272 "WAC category level is not number");
275 ThrowMsg(PowderParserException::ParserFailed,
276 "Too many WAC category levels");
278 if (rating >= MIN_AGE_RATING && rating <= MAX_AGE_RATING) {
280 static_cast<WrtDB::Powder::Description::LevelEnum>(
284 ThrowMsg(PowderParserException::ParserFailed,
285 "WAC category level is out of range ");
291 ThrowMsg(PowderParserException::ParserFailed,
292 "WAC category level is not present in tag");
297 WrtDB::Powder::Description::LevelEntry* m_data;
298 DPL::String m_buffer;
299 static const int MIN_AGE_RATING = 0;
300 static const int MAX_AGE_RATING = 5;
303 class DescriptorSetParser : public DenyUnknownTagsParser
306 typedef WrtDB::Powder::Description::CategoryEntries::iterator CatIter;
307 explicit DescriptorSetParser(WrtDB::Powder::Description* data) :
308 DenyUnknownTagsParser(),
312 #define ELEM(tag) DEFINE_ELEMENT_FUNC(tag, DescriptorSetParser)
323 m_map[DPL::FromUTF32String(L"displayicon")] =
324 DPL::MakeDelegate(this, &DescriptorSetParser::OnIgnoredElement);
327 ElementParserPtr OnElement_aa()
329 m_ages.push_back(StringSet());
330 return ElementParserPtr(new SetOfTextValuesParser(&m_ages.back()));
333 #define GENERATE_ELEMENT_FUNC(element) \
334 ElementParserPtr OnElement_ ## element() \
336 LogInfo("WAC category tag detected: " << # element); \
338 m_data->categories.find(DPL::FromUTF32String(L"" # element)); \
339 if (m_data->categories.end() == category) \
341 std::pair<CatIter, bool> result = \
342 m_data->categories.insert(std::make_pair( \
343 DPL::FromUTF32String(L"" # \
345 WrtDB::Powder::Description:: \
347 category = result.first; \
349 category->second.levels.push_back( \
350 WrtDB::Powder::Description::LevelEntry()); \
351 return ElementParserPtr(new \
353 &category->second.levels.back())); \
356 GENERATE_ELEMENT_FUNC(nu)
357 GENERATE_ELEMENT_FUNC(se)
358 GENERATE_ELEMENT_FUNC(vi)
359 GENERATE_ELEMENT_FUNC(la)
360 GENERATE_ELEMENT_FUNC(dr)
361 GENERATE_ELEMENT_FUNC(ga)
362 GENERATE_ELEMENT_FUNC(ha)
363 GENERATE_ELEMENT_FUNC(ug)
365 #undef GENERATE_ELEMENT_FUNC
367 ElementParserPtr OnIgnoredElement()
369 return ElementParserPtr(new IgnoringParser());
374 if (m_ages.size() > 1) {
375 ThrowMsg(PowderParserException::ParserFailed,
376 "More than one aa tags: not implemented");
377 } else if (m_ages.size() == 1) {
378 if (!m_ages.at(0).empty() && m_ages.at(0).size() <= 1) {
379 DPL::IStringStream str(*m_ages.at(0).begin());
383 ThrowMsg(PowderParserException::ParserFailed,
384 "Invalid number in age rating");
386 m_data->ageRating = rating;
389 ThrowMsg(PowderParserException::ParserFailed,
390 "Not valid age value in aa tag ");
393 // LogInfo("Descriptionset verified: " << *m_data);
397 typedef std::vector<StringSet> AgesTags;
399 WrtDB::Powder::Description* m_data;
402 class DrParser : public DenyUnknownTagsParser
405 DrParser(WrtDB::Powder::Description* data,
406 const DPL::String& host,
407 const DPL::String& path) :
408 DenyUnknownTagsParser(),
414 DEFINE_ELEMENT_FUNC(iriset, DrParser);
415 DEFINE_ELEMENT_FUNC(descriptorset, DrParser);
418 ElementParserPtr OnElement_iriset()
420 m_iriSetOutcomes.push_back(IrisetParserData(m_host, m_path));
421 return ElementParserPtr(new IrisetParser(&m_iriSetOutcomes.back()));
424 ElementParserPtr OnElement_descriptorset()
426 m_descriptions.push_back(WrtDB::Powder::Description());
427 return ElementParserPtr(new
428 DescriptorSetParser(&m_descriptions.back()));
433 if (m_iriSetOutcomes.empty() || m_descriptions.empty()) {
435 PowderParserException::ParserFailed,
436 "dr tag don't contain at lease one iriset and descriptionset ");
438 IriSetOutcomes::const_iterator outIter;
439 for (outIter = m_iriSetOutcomes.begin();
440 outIter != m_iriSetOutcomes.end() && !outIter->m_matched;
443 if (outIter != m_iriSetOutcomes.end()) {
444 LogInfo("Matching iriset found");
445 typedef PowderDescriptions::const_iterator DescIter;
446 for (DescIter descIter = m_descriptions.begin();
447 descIter != m_descriptions.end(); ++descIter) {
448 MergeDescriptions(m_data, *descIter);
451 LogWarning("No matching iriset found");
454 // LogInfo("dr tag verified" << *m_data);
457 typedef std::vector<WrtDB::Powder::Description> PowderDescriptions;
458 PowderDescriptions m_descriptions;
459 typedef std::vector<IrisetParserData> IriSetOutcomes;
460 IriSetOutcomes m_iriSetOutcomes;
461 WrtDB::Powder::Description* m_data;
462 const DPL::String& m_host;
463 const DPL::String& m_path;
466 PowderParser::PowderParser(PowderParserData* data) :
468 m_data(data->description),
473 m_map[DPL::FromUTF32String(L"attribution")] =
474 DPL::MakeDelegate(this, &PowderParser::OnIgnoredElement);
475 DEFINE_ELEMENT_FUNC(dr, PowderParser);
478 ElementParserPtr PowderParser::OnIgnoredElement()
480 return ElementParserPtr(new IgnoringParser());
483 ElementParserPtr PowderParser::OnElement_dr()
485 return ElementParserPtr(new DrParser(m_data, m_host, m_path));
488 void PowderParser::Accept(const Element& /*element*/)
492 void PowderParser::Accept(const XmlAttribute& /*attribute*/)
496 void PowderParser::Accept(const Text& /*text*/)
500 void PowderParser::Verify()
502 // LogInfo("powder tag verified " << *m_data);
505 ElementParserPtr PowderParser::OnDenyElement()
507 return ElementParserPtr(new DenyAllParser());
510 ElementParser::ActionFunc PowderParser::GetElementParser(const DPL::String& /*ns*/,
511 const DPL::String& name)
513 FuncMap::const_iterator it = m_map.find(name);
514 if (it != m_map.end()) {
517 return DPL::MakeDelegate(this, &PowderParser::OnDenyElement);
521 #undef DEFINE_ELEMENT_FUNC