2 * Copyright (c) 2015 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 #include "content/content_filter.h"
21 #include "common/converter.h"
22 #include "common/logger.h"
24 using common::AttributeMatchFlag;
25 using common::CompositeFilterType;
26 using common::ErrorCode;
27 using common::JsonCast;
28 using common::PlatformResult;
35 std::map<std::string, std::string> const attributeNameMap = {
37 {"type", "MEDIA_TYPE"},
38 {"mimeType", "MEDIA_MIME_TYPE"},
39 {"name", "MEDIA_DISPLAY_NAME"},
40 {"title", "MEDIA_TITLE"},
41 {"contentURI", "MEDIA_PATH"},
42 {"thumbnailURIs", "MEDIA_THUMBNAIL_PATH"},
43 {"description", "MEDIA_DESCRIPTION"},
44 {"rating", "MEDIA_RATING"},
45 {"createdDate", "MEDIA_ADDED_TIME"},
46 {"releaseDate", "MEDIA_DATETAKEN"},
47 {"modifiedDate", "MEDIA_MODIFIED_TIME"},
48 {"geolocation.latitude", "MEDIA_LATITUDE"},
49 {"geolocation.longitude", "MEDIA_LONGITUDE"},
50 {"duration", "MEDIA_DURATION"},
51 {"album", "MEDIA_ALBUM"},
52 {"artists", "MEDIA_ARTIST"},
53 {"width", "MEDIA_WIDTH"},
54 {"height", "MEDIA_HEIGHT"},
55 {"genres", "MEDIA_GENRE"},
56 {"size", "MEDIA_SIZE"},
59 std::string escapeValueString(const std::string& data) {
62 // If string won't be resized, then it will be faster
63 out.reserve(data.size());
83 PlatformResult ContentFilter::MapField(const std::string& name,
84 std::string* result) {
86 auto it = attributeNameMap.find(name);
87 if (it != attributeNameMap.end())
91 LoggerE("INVALID_VALUES_ERR");
92 return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
94 return PlatformResult(ErrorCode::NO_ERROR);
97 PlatformResult ContentFilter::BuildQuery(const picojson::object& jsFilter,
98 std::string* queryToCall) {
100 std::vector<std::vector<std::string> > partialqueries;
101 partialqueries.push_back(std::vector<std::string>());
103 visitor.SetOnAttributeFilter([&](const std::string& name,
104 AttributeMatchFlag match_flag,
105 const picojson::value& match_value) {
106 LoggerD("entered OnAttributeFilter");
108 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
111 std::string matchValue;
113 result = MapField(name, &query);
117 if (AttributeMatchFlag::kExactly == match_flag ||
118 AttributeMatchFlag::kFullString == match_flag) {
120 } else if (AttributeMatchFlag::kContains == match_flag ||
121 AttributeMatchFlag::kStartsWith == match_flag ||
122 AttributeMatchFlag::kEndsWith == match_flag) {
124 } else if (AttributeMatchFlag::kExists == match_flag) {
125 query += " IS NOT NULL ";
127 LoggerE("INVALID_VALUES_ERR");
128 return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
131 if (AttributeMatchFlag::kExists != match_flag) {
133 matchValue = escapeValueString(JsonCast<std::string>(match_value));
134 if (name == "type") {
135 if (matchValue == "IMAGE") {
137 } else if (matchValue == "VIDEO") {
139 } else if (matchValue == "AUDIO") {
145 switch (match_flag) {
146 case AttributeMatchFlag::kStartsWith :
147 query += matchValue + "%";
149 case AttributeMatchFlag::kEndsWith :
150 query += "%" + matchValue;
152 case AttributeMatchFlag::kContains :
153 query += "%" + matchValue + "%";
161 partialqueries.back().push_back(query);
166 visitor.SetOnCompositeFilterBegin([&](CompositeFilterType type) {
167 LoggerD("entered OnCompositeFilterBegin");
168 partialqueries.push_back(std::vector<std::string>());
169 return PlatformResult(ErrorCode::NO_ERROR);
172 visitor.SetOnCompositeFilterEnd([&](CompositeFilterType calType) {
173 LoggerD("entered OnCompositeFilterEnd");
174 std::string finalQuery;
175 std::string separator;
177 if (CompositeFilterType::kUnion == calType)
182 if (partialqueries.back().empty()) {
183 partialqueries.pop_back();
184 return PlatformResult(ErrorCode::NO_ERROR);
186 if (partialqueries.back().size() != 1)
187 finalQuery.append("(");
189 for (unsigned long i = 0; i < partialqueries.back().size(); i++) {
190 finalQuery += partialqueries.back().at(i);
191 if (i != partialqueries.back().size() - 1) {
192 finalQuery += separator;
196 if (partialqueries.back().size() != 1)
197 finalQuery.append(")");
198 partialqueries.pop_back();
199 partialqueries.back().push_back(finalQuery);
201 return PlatformResult(ErrorCode::NO_ERROR);
204 visitor.SetOnAttributeRangeFilter([&](const std::string& name,
205 const picojson::value& initial_value,
206 const picojson::value& end_value) {
207 LoggerD("entered OnAttributeFilter");
209 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
210 std::string query = "";
211 std::string paramName;
212 result = MapField(name, ¶mName);
216 std::string initialValue = escapeValueString(JsonCast<std::string>(initial_value));
217 std::string endValue = escapeValueString(JsonCast<std::string>(end_value));
220 query += initialValue;
226 partialqueries.back().push_back(query);
231 if (!visitor.Visit(jsFilter)) {
232 LoggerE("INVALID_VALUES_ERR");
233 return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
236 if (partialqueries.empty()) {
237 LoggerE("Filter parsing error!");
238 return PlatformResult(ErrorCode::SYNTAX_ERR);
240 if (partialqueries.back().empty()) {
241 LoggerD("Resolved to empty string!");
243 return PlatformResult(ErrorCode::NO_ERROR);
246 *queryToCall = partialqueries.back().front();
247 return PlatformResult(ErrorCode::NO_ERROR);
250 } // namespace content
251 } // namespace extension