1 // Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/content_filter.h"
9 #include "common/converter.h"
10 #include "common/logger.h"
12 using common::AttributeMatchFlag;
13 using common::CompositeFilterType;
14 using common::ErrorCode;
15 using common::JsonCast;
16 using common::PlatformResult;
23 std::map<std::string, std::string> const attributeNameMap = {
25 {"type", "MEDIA_TYPE"},
26 {"mimeType", "MEDIA_MIME_TYPE"},
27 {"name", "MEDIA_DISPLAY_NAME"},
28 {"title", "MEDIA_TITLE"},
29 {"contentURI", "MEDIA_PATH"},
30 {"thumbnailURIs", "MEDIA_THUMBNAIL_PATH"},
31 {"description", "MEDIA_DESCRIPTION"},
32 {"rating", "MEDIA_RATING"},
33 {"createdDate", "MEDIA_ADDED_TIME"},
34 {"releaseDate", "MEDIA_DATETAKEN"},
35 {"modifiedDate", "MEDIA_MODIFIED_TIME"},
36 {"geolocation.latitude", "MEDIA_LATITUDE"},
37 {"geolocation.longitude", "MEDIA_LONGITUDE"},
38 {"duration", "MEDIA_DURATION"},
39 {"album", "MEDIA_ALBUM"},
40 {"artists", "MEDIA_ARTIST"},
41 {"width", "MEDIA_WIDTH"},
42 {"height", "MEDIA_HEIGHT"},
43 {"genres", "MEDIA_GENRE"},
44 {"size", "MEDIA_SIZE"},
47 std::string escapeValueString(const std::string& data) {
49 // If string won't be resized, then it will be faster
50 out.reserve(data.size());
70 PlatformResult ContentFilter::MapField(const std::string& name,
71 std::string* result) {
72 auto it = attributeNameMap.find(name);
73 if (it != attributeNameMap.end())
76 return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
78 return PlatformResult(ErrorCode::NO_ERROR);
81 PlatformResult ContentFilter::BuildQuery(const picojson::object& jsFilter,
82 std::string* queryToCall) {
83 std::vector<std::vector<std::string> > partialqueries;
84 partialqueries.push_back(std::vector<std::string>());
86 visitor.SetOnAttributeFilter([&](const std::string& name,
87 AttributeMatchFlag match_flag,
88 const picojson::value& match_value) {
89 LoggerD("entered OnAttributeFilter");
91 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
94 std::string matchValue;
96 result = MapField(name, &query);
100 if (AttributeMatchFlag::kExactly == match_flag ||
101 AttributeMatchFlag::kFullString == match_flag) {
103 } else if (AttributeMatchFlag::kContains == match_flag ||
104 AttributeMatchFlag::kStartsWith == match_flag ||
105 AttributeMatchFlag::kEndsWith == match_flag) {
107 } else if (AttributeMatchFlag::kExists == match_flag) {
108 query += " IS NOT NULL ";
110 return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
113 if (AttributeMatchFlag::kExists != match_flag) {
115 matchValue = escapeValueString(JsonCast<std::string>(match_value));
116 if (name == "type") {
117 if (matchValue == "IMAGE") {
119 } else if (matchValue == "VIDEO") {
121 } else if (matchValue == "AUDIO") {
131 partialqueries.back().push_back(query);
136 visitor.SetOnCompositeFilterBegin([&](CompositeFilterType type) {
137 LoggerD("entered OnCompositeFilterBegin");
138 partialqueries.push_back(std::vector<std::string>());
139 return PlatformResult(ErrorCode::NO_ERROR);
142 visitor.SetOnCompositeFilterEnd([&](CompositeFilterType calType) {
143 LoggerD("entered OnCompositeFilterEnd");
144 std::string finalQuery;
145 std::string separator;
147 if (CompositeFilterType::kUnion == calType)
152 if (partialqueries.back().empty()) {
153 partialqueries.pop_back();
154 return PlatformResult(ErrorCode::NO_ERROR);
156 if (partialqueries.back().size() != 1)
157 finalQuery.append("(");
159 for (unsigned long i = 0; i < partialqueries.back().size(); i++) {
160 finalQuery += partialqueries.back().at(i);
161 if (i != partialqueries.back().size() - 1) {
162 finalQuery += separator;
166 if (partialqueries.back().size() != 1)
167 finalQuery.append(")");
168 partialqueries.pop_back();
169 partialqueries.back().push_back(finalQuery);
171 return PlatformResult(ErrorCode::NO_ERROR);
174 visitor.SetOnAttributeRangeFilter([&](const std::string& name,
175 const picojson::value& initial_value,
176 const picojson::value& end_value) {
177 LoggerD("entered OnAttributeFilter");
179 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
180 std::string query = "";
181 std::string paramName;
182 result = MapField(name, ¶mName);
186 std::string initialValue = escapeValueString(JsonCast<std::string>(initial_value));
187 std::string endValue = escapeValueString(JsonCast<std::string>(end_value));
190 query += initialValue;
196 partialqueries.back().push_back(query);
201 if (!visitor.Visit(jsFilter)) {
202 return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
205 if (partialqueries.empty()) {
206 LoggerE("Filter parsing error!");
207 return PlatformResult(ErrorCode::SYNTAX_ERR);
209 if (partialqueries.back().empty()) {
210 LoggerD("Resolved to empty string!");
212 return PlatformResult(ErrorCode::NO_ERROR);
215 *queryToCall = partialqueries.back().front();
216 return PlatformResult(ErrorCode::NO_ERROR);
219 } // namespace content
220 } // namespace extension