obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
MessagingInstance::getInstance().PostMessage(json->serialize().c_str());
}
- } catch (const common::PlatformException& err) {
+ } catch (const PlatformException& err) {
LoggerE("Error while calling findConversations callback: %s (%s)",
(err.name()).c_str(), (err.message()).c_str());
} catch (...) {
return op_id++;
}
-//void EmailManager::findFolders(FoldersCallbackData* callback)
-//{
-// LoggerD("Entered");
-//
-// if (!callback){
-// LoggerE("Callback is null");
-// return;
-// }
-//
-// int ret = EMAIL_ERROR_UNKNOWN;
-// int account_id = ACCOUNT_ID_NOT_INITIALIZED;
-// email_mailbox_t* mailboxes = NULL;
-// email_mailbox_t* nth_mailbox = NULL;
-// int mailboxes_count;
-//
-// try {
-// std::lock_guard<std::mutex> lock(m_mutex);
-//
-// Tizen::AbstractFilterPtr filter = callback->getFilter();
-// if (!filter) {
-// LoggerE("Filter not provided");
-// throw UnknownException("Filter not provided");
-// }
-//
-// for(FilterIterator it(filter); false == it.isEnd(); it++) {
-//
-// if(FIS_COMPOSITE_START == it.getState()) {
-// CompositeFilterPtr cf = castToCompositeFilter((*it));
-// if(cf && INTERSECTION != cf->getType()) {
-// LoggerE("[ERROR] >>> invalid Filter type: %d", cf->getType());
-// throw TypeMismatchException("Invalid Filter Type");
-// }
-// }
-// else if(FIS_ATTRIBUTE_FILTER == it.getState()) {
-// AttributeFilterPtr attrf = castToAttributeFilter((*it));
-// if(attrf) {
-// const std::string attr_name = attrf->getAttributeName();
-// if (FIND_FOLDERS_ATTRIBUTE_ACCOUNTID_NAME == attr_name) {
-// account_id = static_cast<int>(attrf->getMatchValue()->toLong());
-// } else {
-// LoggerE("The attribute name: %s is invalid", attr_name.c_str());
-// throw InvalidValuesException("The attribute name is invalid");
-// }
-// }
-// }
-// }
-//
-// LoggerD("Listing folders for account ID: %d", account_id);
-// if (account_id > 0) {
-// ret = email_get_mailbox_list(account_id,
-// -1,
-// &mailboxes,
-// &mailboxes_count);
-// if (EMAIL_ERROR_NONE != ret || !mailboxes) {
-// LoggerE("Cannot get folders: %d", ret);
-// throw Common::UnknownException(
-// "Platform error, cannot get folders");
-// }
-//
-// if (mailboxes_count <= 0) {
-// LoggerD("Empty mailboxes");
-// }
-// else {
-// LoggerD("Founded mailboxes: %d", mailboxes_count);
-//
-// nth_mailbox = mailboxes;
-// for (int i = 0; i < mailboxes_count; ++i) {
-// std::shared_ptr<MessageFolder> fd;
-// fd = std::make_shared<MessageFolder>(*nth_mailbox);
-// callback->addFolder(fd);
-// nth_mailbox++;
-// }
-// }
-// }
-// } catch (const BasePlatformException& err) {
-// LoggerE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
-// callback->setError(err.getName(), err.getMessage());
-// } catch (...) {
-// LoggerE("Messages update failed");
-// callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
-// "Messages update failed");
-// }
-//
-// if (mailboxes != NULL) {
-// if (EMAIL_ERROR_NONE != email_free_mailbox(&mailboxes,
-// mailboxes_count)) {
-// LoggerW("Free mailboxes failed: %d", ret);
-// }
-// }
-//
-// //Complete task
-// LoggerD("callback: %p error:%d folders.size()=%d", callback, callback->isError(),
-// callback->getFolders().size());
-//
-// JSContextRef context = callback->getContext();
-// if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
-// LoggerE("context was closed");
-// delete callback;
-// callback = NULL;
-// return;
-// }
-//
-// try {
-// if (callback->isError()) {
-// LoggerD("Calling error callback");
-// JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
-// callback->getErrorName(),
-// callback->getErrorMessage());
-// callback->callErrorCallback(errobj);
-// } else {
-// LoggerD("Calling success callback");
-// JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<FolderPtr,
-// JSMessageFolder>(context, callback->getFolders());
-// callback->callSuccessCallback(js_obj);
-// }
-// } catch (const BasePlatformException& err) {
-// LoggerE("Error while calling findFolders callback: %s (%s)",
-// (err.getName()).c_str(), (err.getMessage()).c_str());
-// } catch (...) {
-// LoggerE("Unknown error when calling findFolders callback.");
-// }
-//
-// delete callback;
-// callback = NULL;
-//}
+void EmailManager::findFolders(FoldersCallbackData* callback)
+{
+ LoggerD("Entered");
+
+ if (!callback){
+ LoggerE("Callback is null");
+ return;
+ }
+
+ int ret = EMAIL_ERROR_UNKNOWN;
+ int account_id = ACCOUNT_ID_NOT_INITIALIZED;
+ email_mailbox_t* mailboxes = NULL;
+ email_mailbox_t* nth_mailbox = NULL;
+ int mailboxes_count;
+
+ try {
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ tizen::AbstractFilterPtr filter = callback->getFilter();
+ if (!filter) {
+ LoggerE("Filter not provided");
+ throw UnknownException("Filter not provided");
+ }
+
+ for(FilterIterator it(filter); false == it.isEnd(); it++) {
+
+ if(FIS_COMPOSITE_START == it.getState()) {
+ CompositeFilterPtr cf = castToCompositeFilter((*it));
+ if(cf && INTERSECTION != cf->getType()) {
+ LoggerE("[ERROR] >>> invalid Filter type: %d", cf->getType());
+ throw TypeMismatchException("Invalid Filter Type");
+ }
+ }
+ else if(FIS_ATTRIBUTE_FILTER == it.getState()) {
+ AttributeFilterPtr attrf = castToAttributeFilter((*it));
+ if(attrf) {
+ const std::string attr_name = attrf->getAttributeName();
+ if (FIND_FOLDERS_ATTRIBUTE_ACCOUNTID_NAME == attr_name) {
+ account_id = static_cast<int>(attrf->getMatchValue()->toLong());
+ } else {
+ LoggerE("The attribute name: %s is invalid", attr_name.c_str());
+ throw InvalidValuesException("The attribute name is invalid");
+ }
+ }
+ }
+ }
+
+ LoggerD("Listing folders for account ID: %d", account_id);
+ if (account_id > 0) {
+ ret = email_get_mailbox_list(account_id,
+ -1,
+ &mailboxes,
+ &mailboxes_count);
+ if (EMAIL_ERROR_NONE != ret || !mailboxes) {
+ LoggerE("Cannot get folders: %d", ret);
+ throw UnknownException("Platform error, cannot get folders");
+ }
+
+ if (mailboxes_count <= 0) {
+ LoggerD("Empty mailboxes");
+ }
+ else {
+ LoggerD("Founded mailboxes: %d", mailboxes_count);
+
+ nth_mailbox = mailboxes;
+ for (int i = 0; i < mailboxes_count; ++i) {
+ std::shared_ptr<MessageFolder> fd;
+ fd = std::make_shared<MessageFolder>(*nth_mailbox);
+ callback->addFolder(fd);
+ nth_mailbox++;
+ }
+ }
+ }
+ } catch (const PlatformException& err) {
+ LoggerE("%s (%s)", (err.name()).c_str(), (err.message()).c_str());
+ callback->setError(err.name(), err.message());
+ } catch (...) {
+ LoggerE("Messages update failed");
+ UnknownException ex("Messages update failed");
+ callback->setError(ex.name(), ex.message());
+ }
+
+ if (mailboxes != NULL) {
+ if (EMAIL_ERROR_NONE != email_free_mailbox(&mailboxes,
+ mailboxes_count)) {
+ LoggerW("Free mailboxes failed: %d", ret);
+ }
+ }
+
+ //Complete task
+ LoggerD("callback: %p error:%d folders.size()=%d", callback, callback->isError(),
+ callback->getFolders().size());
+
+ try {
+ if (callback->isError()) {
+ LoggerD("Calling error callback");
+ MessagingInstance::getInstance().PostMessage(callback->getJson()->serialize().c_str());
+ } else {
+ LoggerD("Calling success callback");
+ auto json = callback->getJson();
+ picojson::object& obj = json->get<picojson::object>();
+
+ std::vector<picojson::value> response;
+ auto folders = callback->getFolders();
+ std::for_each(folders.begin(), folders.end(),
+ [&response](std::shared_ptr<MessageFolder> &folder) {
+ response.push_back(MessagingUtil::folderToJson(folder));
+ }
+ );
+ obj[JSON_DATA] = picojson::value(response);
+ obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+ MessagingInstance::getInstance().PostMessage(json->serialize().c_str());
+ }
+ } catch (const PlatformException& err) {
+ LoggerE("Error while calling findFolders callback: %s (%s)",
+ (err.name()).c_str(), (err.message()).c_str());
+ } catch (...) {
+ LoggerE("Unknown error when calling findFolders callback.");
+ }
+
+ delete callback;
+ callback = NULL;
+}
void EmailManager::removeConversations(ConversationCallbackData* callback)
{
void updateMessages(MessagesCallbackUserData* callback);
void findMessages(FindMsgCallbackUserData* callback);
void findConversations(ConversationCallbackData* callback);
-// void findFolders(FoldersCallbackData* callback);
+ void findFolders(FoldersCallbackData* callback);
void removeConversations(ConversationCallbackData* callback);
void sendMessage(MessageRecipientsCallbackData* callback);
--- /dev/null
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "folders_callback_data.h"
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+
+FoldersCallbackData::FoldersCallbackData():
+ m_is_error(false)
+{
+}
+
+FoldersCallbackData::~FoldersCallbackData() {
+}
+
+void FoldersCallbackData::addFolder(std::shared_ptr<MessageFolder> folder)
+{
+ m_folders.push_back(folder);
+}
+
+const std::vector<std::shared_ptr<MessageFolder>>& FoldersCallbackData::getFolders() const
+{
+ return m_folders;
+}
+
+void FoldersCallbackData::setFilter(tizen::AbstractFilterPtr filter)
+{
+ m_filter = filter;
+}
+
+tizen::AbstractFilterPtr FoldersCallbackData::getFilter() const
+{
+ return m_filter;
+}
+
+void FoldersCallbackData::setError(const std::string& err_name,
+ const std::string& err_message)
+{
+ // keep only first error in chain
+ if (!m_is_error) {
+ m_is_error = true;
+ m_err_name = err_name;
+ m_err_message = err_message;
+
+ picojson::object& obj = m_json->get<picojson::object>();
+ obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+ auto obj_error = picojson::object();
+ obj_error[JSON_ERROR_NAME] = picojson::value(err_name);
+ obj_error[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+ obj[JSON_DATA] = picojson::value(obj_error);
+ }
+}
+
+bool FoldersCallbackData::isError() const
+{
+ return m_is_error;
+}
+
+std::string FoldersCallbackData::getErrorName() const
+{
+ return m_err_name;
+}
+
+std::string FoldersCallbackData::getErrorMessage() const
+{
+ return m_err_message;
+}
+
+}//messaging
+}//extension
--- /dev/null
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_FOLDERS_CALLBACK_DATA_H__
+#define __TIZEN_FOLDERS_CALLBACK_DATA_H__
+
+#include "common/callback_user_data.h"
+
+#include <memory>
+#include <vector>
+#include <string>
+
+#include "MsgCommon/AbstractFilter.h"
+
+#include "message_folder.h"
+
+namespace extension {
+namespace messaging {
+
+class MessageFolder;
+
+class FoldersCallbackData: public common::CallbackUserData {
+public:
+ FoldersCallbackData();
+ virtual ~FoldersCallbackData();
+
+ void addFolder(std::shared_ptr<MessageFolder> folder);
+ const std::vector<std::shared_ptr<MessageFolder>>& getFolders() const;
+
+ void setFilter(tizen::AbstractFilterPtr filter);
+ tizen::AbstractFilterPtr getFilter() const;
+
+ void setError(const std::string& err_name,
+ const std::string& err_message);
+ bool isError() const;
+ std::string getErrorName() const;
+ std::string getErrorMessage() const;
+
+private:
+ std::vector<std::shared_ptr<MessageFolder>> m_folders;
+ tizen::AbstractFilterPtr m_filter;
+ bool m_is_error;
+ std::string m_err_name;
+ std::string m_err_message;
+
+};
+
+}//messaging
+}//extension
+
+#endif /* __TIZEN_FOLDERS_CALLBACK_DATA_H__ */
#include "messages_callback_user_data.h"
#include "conversation_callback_data.h"
#include "find_msg_callback_user_data.h"
+#include "folders_callback_data.h"
namespace extension {
namespace messaging {
virtual void findMessages(FindMsgCallbackUserData* callback) = 0;
virtual void findConversations(ConversationCallbackData* callback) = 0;
virtual void removeConversations(ConversationCallbackData* callback) = 0;
- virtual void findFolders() = 0;
+ virtual void findFolders(FoldersCallbackData* callback) = 0;
// Listeners registration/removal is common for all types of storage
// and does not have to be overwritten in derived classes.
}
}
-void MessageStorageEmail::findFolders()
+static gboolean findFoldersTask(void* data)
{
LoggerD("Entered");
- //TODO add implementation
+
+ FoldersCallbackData *callback = static_cast<FoldersCallbackData*>(data);
+ EmailManager::getInstance().findFolders(callback);
+
+ return FALSE;
+}
+
+void MessageStorageEmail::findFolders(FoldersCallbackData* callback)
+{
+ LoggerD("Entered");
+
+ if (!callback) {
+ LoggerE("Callback is null");
+ throw common::UnknownException("Callback is null");
+ }
+
+ guint id = g_idle_add(findFoldersTask, static_cast<void*>(callback));
+ if (!id) {
+ LoggerE("g_idle_add failed");
+ delete callback;
+ callback = NULL;
+ }
}
} //messaging
virtual void findMessages(FindMsgCallbackUserData* callback);
virtual void findConversations(ConversationCallbackData* callback);
virtual void removeConversations(ConversationCallbackData* callback);
- virtual void findFolders();
+ virtual void findFolders(FoldersCallbackData* callback);
};
} //messaging
'message_conversation.cc',
'message_conversation.h',
'conversation_callback_data.cc',
- 'conversation_callback_data.h'
+ 'conversation_callback_data.h',
+ 'folders_callback_data.cc',
+ 'folders_callback_data.h'
],
'includes': [
'../common/pkg-config.gypi',
{name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
]);
+ var self = this;
+
bridge.async({
cmd: 'MessageStorage_findFolders',
args: {
filter: args.filter,
sort: args.sort,
limit: args.limit,
- offset: args.offset
+ offset: args.offset,
+ serviceId: self.service.id
}
}).then({
success: function (data) {
- var conversations = [];
+ var folders = [];
data.forEach(function (el) {
- conversations.push(new MessageConversation(el));
+ folders.push(new MessageFolder(el));
});
- args.successCallback.call(null, messages);
+ args.successCallback.call(null, folders);
},
error: function (e) {
if (args.errorCallback) {
if (args.foldersChangeCallback.foldersadded) {
var folders = [];
data.forEach(function (el) {
- folders.push(new tizen.MessageFolder(el));
+ folders.push(new MessageFolder(el));
});
args.foldersChangeCallback.foldersadded.call(null, folders);
}
if (args.foldersChangeCallback.foldersupdated) {
var folders = [];
data.forEach(function (el) {
- folders.push(new tizen.MessageFolder(el));
+ folders.push(new MessageFolder(el));
});
args.foldersChangeCallback.foldersupdated.call(null, folders);
}
if (args.foldersChangeCallback.foldersremoved) {
var folders = [];
data.forEach(function (el) {
- folders.push(new tizen.MessageFolder(el));
+ folders.push(new MessageFolder(el));
});
args.foldersChangeCallback.foldersremoved.call(null, folders);
}
#include "messages_change_callback.h"
#include "messages_callback_user_data.h"
#include "find_msg_callback_user_data.h"
+#include "folders_callback_data.h"
#include "messaging_manager.h"
#include "messaging_util.h"
#include "message_storage.h"
picojson::object data = args.get(JSON_DATA).get<picojson::object>();
const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+ // TODO add support to AttributeRangeFilter
auto filter = MessagingUtil::jsonToAttributeFilter(data);
auto sortMode = MessagingUtil::jsonToSortMode(data);
long limit = static_cast<long>
picojson::object data = args.get(JSON_DATA).get<picojson::object>();
const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+ // TODO add support to AttributeRangeFilter
auto filter = MessagingUtil::jsonToAttributeFilter(data);
auto sortMode = MessagingUtil::jsonToSortMode(data);
long limit = static_cast<long>
picojson::object& out)
{
LoggerD("Entered");
+
+ picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+ const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+ // TODO add support to AttributeRangeFilter
+ auto filter = MessagingUtil::jsonToAttributeFilter(data);
+ int serviceId = static_cast<int>(data.at(FUNCTIONS_HIDDEN_ARGS_SERVICE_ID).get<double>());
+
+ FoldersCallbackData* callback = new FoldersCallbackData();
+ callback->setFilter(filter);
+
+ auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+ picojson::object& obj = json->get<picojson::object>();
+ obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+ callback->setJson(json);
+
+ auto storage = MessagingManager::getInstance().getMessageServiceEmail(serviceId)->getMsgStorage();
+ storage->findFolders(callback);
}
void MessagingInstance::MessageStorageAddMessagesChangeListener(const picojson::value& args,
const char* MESSAGE_ATTACHMENT_ATTRIBUTE_MIME_TYPE = "mimeType";
const char* MESSAGE_ATTACHMENT_ATTRIBUTE_FILE_PATH = "filePath";
+const char* MESSAGE_FOLDER_ATTRIBUTE_ID = "id";
+const char* MESSAGE_FOLDER_ATTRIBUTE_PARENT_ID = "parentId";
const char* MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID = "serviceId";
+const char* MESSAGE_FOLDER_ATTRIBUTE_CONTENT_TYPE = "contentType";
+const char* MESSAGE_FOLDER_ATTRIBUTE_NAME = "name";
+const char* MESSAGE_FOLDER_ATTRIBUTE_PATH = "path";
+const char* MESSAGE_FOLDER_ATTRIBUTE_TYPE = "type";
+const char* MESSAGE_FOLDER_ATTRIBUTE_SYNCHRONIZABLE = "synchronizable";
const char* MESSAGE_CONVERSATION_ATTRIBUTE_ID = "id";
const char* MESSAGE_CONVERSATION_ATTRIBUTE_TYPE = "type";
{MessageType::EMAIL, TYPE_EMAIL}
};
+const std::string FOLDER_TYPE_INBOX = "INBOX";
+const std::string FOLDER_TYPE_OUTBOX = "OUTBOX";
+const std::string FOLDER_TYPE_DRAFTS = "DRAFTS";
+const std::string FOLDER_TYPE_SENTBOX = "SENTBOX";
+
} // namespace
+std::string MessagingUtil::messageFolderTypeToString(MessageFolderType type)
+{
+ switch(type) {
+ case MessageFolderType::MESSAGE_FOLDER_TYPE_INBOX:
+ return FOLDER_TYPE_INBOX;
+ case MessageFolderType::MESSAGE_FOLDER_TYPE_OUTBOX:
+ return FOLDER_TYPE_OUTBOX;
+ case MessageFolderType::MESSAGE_FOLDER_TYPE_DRAFTS:
+ return FOLDER_TYPE_DRAFTS;
+ case MessageFolderType::MESSAGE_FOLDER_TYPE_SENTBOX:
+ return FOLDER_TYPE_SENTBOX;
+ default:
+ return "";
+ }
+}
+
MessageType MessagingUtil::stringToMessageType(std::string str)
{
try {
return v;
}
+picojson::value MessagingUtil::folderToJson(std::shared_ptr<MessageFolder> folder)
+{
+ LoggerD("Entered");
+
+ picojson::object o;
+
+ o[MESSAGE_FOLDER_ATTRIBUTE_ID] = picojson::value(folder->getId());
+ o[MESSAGE_FOLDER_ATTRIBUTE_PARENT_ID] =
+ folder->isParentIdSet()
+ ? picojson::value(folder->getParentId())
+ : picojson::value();
+ o[MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID] = picojson::value(folder->getServiceId());
+ o[MESSAGE_FOLDER_ATTRIBUTE_CONTENT_TYPE] = picojson::value(folder->getContentType());
+ o[MESSAGE_FOLDER_ATTRIBUTE_NAME] = picojson::value(folder->getName());
+ o[MESSAGE_FOLDER_ATTRIBUTE_PATH] = picojson::value(folder->getPath());
+ o[MESSAGE_FOLDER_ATTRIBUTE_TYPE] =
+ picojson::value(MessagingUtil::messageFolderTypeToString(folder->getType()));
+ o[MESSAGE_FOLDER_ATTRIBUTE_SYNCHRONIZABLE] = picojson::value(folder->getSynchronizable());
+
+ picojson::value v(o);
+ return v;
+}
+
std::shared_ptr<Message> MessagingUtil::jsonToMessage(const picojson::value& json)
{
LoggerD("Entered");
#include "MsgCommon/SortMode.h";
#include "MsgCommon/AttributeFilter.h"
+#include "MsgCommon/AbstractFilter.h"
+
+#include "message_folder.h"
namespace extension {
namespace messaging {
class MessagingUtil {
public:
+ static std::string messageFolderTypeToString(MessageFolderType);
static MessageType stringToMessageType(std::string);
static std::string messageTypeToString(MessageType);
static std::string ltrim(const std::string& input);
static picojson::value messageBodyToJson(std::shared_ptr<MessageBody> body);
static picojson::value messageToJson(std::shared_ptr<Message> message);
static picojson::value conversationToJson(std::shared_ptr<MessageConversation> conversation);
+ static picojson::value folderToJson(std::shared_ptr<MessageFolder> folder);
static std::shared_ptr<Message> jsonToMessage(const picojson::value& json);
static tizen::SortModePtr jsonToSortMode(const picojson::object& json);
static tizen::AttributeFilterPtr jsonToAttributeFilter(const picojson::object& json);