00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __PION_JSONCODEC_HEADER__
00021 #define __PION_JSONCODEC_HEADER__
00022
00023 #include <vector>
00024 #include <map>
00025 #include <queue>
00026 #include <pion/PionConfig.hpp>
00027 #include <pion/platform/Codec.hpp>
00028 #include <yajl/yajl_gen.h>
00029
00030
00031 namespace pion {
00032 namespace plugins {
00033
00034
00035 struct Context;
00036
00041 class JSONCodec :
00042 public pion::platform::Codec
00043 {
00044 public:
00045
00046
00047
00048
00050 class EmptyFieldException : public PionException {
00051 public:
00052 EmptyFieldException(const std::string& codec_id)
00053 : PionException("JSONCodec configuration includes an empty field name: ", codec_id) {}
00054 };
00055
00057 class EmptyTermException : public PionException {
00058 public:
00059 EmptyTermException(const std::string& codec_id)
00060 : PionException("JSONCodec configuration is missing a term identifier: ", codec_id) {}
00061 };
00062
00063
00065 JSONCodec(void)
00066 : pion::platform::Codec(),
00067 m_flush_after_write(false), m_yajl_generator(NULL), m_yajl_handle(NULL),
00068 m_no_events_written(true), m_first_read_attempt(true)
00069 {}
00070
00072 virtual ~JSONCodec() {
00073 if (m_yajl_generator)
00074 yajl_gen_free(m_yajl_generator);
00075 if (m_yajl_handle)
00076 yajl_free(m_yajl_handle);
00077 }
00078
00080 virtual const std::string& getContentType(void) const { return CONTENT_TYPE; }
00081
00087 virtual pion::platform::CodecPtr clone(void) const;
00088
00095 virtual void write(std::ostream& out, const pion::platform::Event& e);
00096
00102 virtual void finish(std::ostream& out);
00103
00111 virtual bool read(std::istream& in, pion::platform::Event& e);
00112
00120 virtual void setConfig(const pion::platform::Vocabulary& v, const xmlNodePtr config_ptr);
00121
00128 virtual void updateVocabulary(const pion::platform::Vocabulary& v);
00129
00131 inline void reset(void) {
00132 m_field_map.clear();
00133 m_format.clear();
00134 }
00135
00137 struct JSONField {
00138 JSONField(const std::string& f, const pion::platform::Vocabulary::Term& t)
00139 : field_name(f), term(t)
00140 {}
00141
00143 std::string field_name;
00144
00146 pion::platform::Vocabulary::Term term;
00147
00149 PionTimeFacet time_facet;
00150 };
00151
00153 typedef boost::shared_ptr<JSONField> JSONFieldPtr;
00154
00156 typedef PION_HASH_MAP<std::string,
00157 JSONFieldPtr,
00158 PION_HASH_STRING> FieldMap;
00159
00161 typedef std::vector<JSONFieldPtr> CurrentFormat;
00162
00164 typedef PION_HASH_MULTIMAP<pion::platform::Vocabulary::TermRef, std::string>
00165 JSONObject;
00166
00168 typedef boost::shared_ptr<JSONObject> JSONObjectPtr;
00169
00171 typedef std::queue<JSONObjectPtr> JSONObjectQueue;
00172
00173 private:
00174
00176 typedef std::istream::traits_type traits_type;
00177
00179 typedef std::basic_streambuf<
00180 std::istream::char_type,
00181 std::istream::traits_type> streambuf_type;
00182
00184 typedef std::istream::int_type int_type;
00185
00192 inline void mapFieldToTerm(const std::string& field,
00193 const pion::platform::Vocabulary::Term& term);
00194
00195
00197 static const std::string CONTENT_TYPE;
00198
00200 static const std::string FIELD_ELEMENT_NAME;
00201
00203 static const std::string TERM_ATTRIBUTE_NAME;
00204
00206 static const unsigned int READ_BUFFER_SIZE;
00207
00209 static std::string INDENT_STRING;
00210
00211
00213 FieldMap m_field_map;
00214
00216 std::map<pion::platform::Vocabulary::TermRef, JSONFieldPtr>
00217 m_JSON_field_ptr_map;
00218
00220 CurrentFormat m_format;
00221
00223 bool m_flush_after_write;
00224
00226 yajl_gen m_yajl_generator;
00227
00229 yajl_handle m_yajl_handle;
00230
00232 JSONObjectQueue m_json_object_queue;
00233
00235 boost::shared_ptr<Context> m_context;
00236
00238 bool m_no_events_written;
00239
00241 bool m_first_read_attempt;
00242 };
00243
00244
00245
00246
00247 inline void JSONCodec::mapFieldToTerm(const std::string& field,
00248 const pion::platform::Vocabulary::Term& term)
00249 {
00250 if (m_field_map[field])
00251 throw PionException("Duplicate Field Name");
00252
00253
00254 JSONFieldPtr field_ptr(new JSONField(field, term));
00255 switch (term.term_type) {
00256 case pion::platform::Vocabulary::TYPE_DATE_TIME:
00257 case pion::platform::Vocabulary::TYPE_DATE:
00258 case pion::platform::Vocabulary::TYPE_TIME:
00259 field_ptr->time_facet.setFormat(term.term_format);
00260 break;
00261 default:
00262 break;
00263 }
00264
00265
00266 m_field_map[field] = field_ptr;
00267
00268
00269 m_format.push_back(field_ptr);
00270 }
00271
00272
00273 struct Context {
00274 Context(const JSONCodec::FieldMap& field_map, JSONCodec::JSONObjectQueue& json_object_queue)
00275 : field_map(field_map), json_object_queue(json_object_queue)
00276 , m_array_started(false), m_array_ended(false)
00277 {}
00278
00279 const JSONCodec::FieldMap& field_map;
00280 JSONCodec::JSONObjectQueue& json_object_queue;
00281 JSONCodec::JSONObjectPtr json_object_ptr;
00282 pion::platform::Vocabulary::TermRef term_ref;
00283 bool m_array_started;
00284 bool m_array_ended;
00285 };
00286
00287 }
00288 }
00289
00290 #endif
00291