00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __PION_XMLCODEC_HEADER__
00021 #define __PION_XMLCODEC_HEADER__
00022
00023 #include <vector>
00024 #include <map>
00025 #include <queue>
00026 #include <libxml/tree.h>
00027 #include <libxml/xmlwriter.h>
00028 #include <libxml/xmlreader.h>
00029 #include <pion/PionConfig.hpp>
00030 #include <pion/platform/Codec.hpp>
00031
00032
00033 namespace pion {
00034 namespace plugins {
00035
00036
00041 class XMLCodec :
00042 public pion::platform::Codec
00043 {
00044 public:
00046 class EmptyFieldException : public PionException {
00047 public:
00048 EmptyFieldException(const std::string& codec_id)
00049 : PionException("XMLCodec configuration includes an empty field name: ", codec_id) {}
00050 };
00051
00053 class EmptyTermException : public PionException {
00054 public:
00055 EmptyTermException(const std::string& codec_id)
00056 : PionException("XMLCodec configuration is missing a term identifier: ", codec_id) {}
00057 };
00058
00059
00061 XMLCodec(void) :
00062 pion::platform::Codec(),
00063 m_flush_after_write(false), m_xml_writer(NULL), m_buf(NULL), m_xml_reader(NULL),
00064 m_no_events_written(true), m_first_read_attempt(true)
00065 {}
00066
00068 virtual ~XMLCodec() {
00069 if (m_xml_reader)
00070 xmlFreeTextReader(m_xml_reader);
00071 if (m_xml_writer)
00072 xmlFreeTextWriter(m_xml_writer);
00073 if (m_buf)
00074 xmlBufferFree(m_buf);
00075 }
00076
00078 virtual const std::string& getContentType(void) const { return CONTENT_TYPE; }
00079
00085 virtual pion::platform::CodecPtr clone(void) const;
00086
00093 virtual void write(std::ostream& out, const pion::platform::Event& e);
00094
00100 virtual void finish(std::ostream& out);
00101
00109 virtual bool read(std::istream& in, pion::platform::Event& e);
00110
00118 virtual void setConfig(const pion::platform::Vocabulary& v, const xmlNodePtr config_ptr);
00119
00126 virtual void updateVocabulary(const pion::platform::Vocabulary& v);
00127
00129 inline void reset(void) {
00130 m_field_map.clear();
00131 m_format.clear();
00132 }
00133
00135 struct XMLField {
00136 XMLField(const std::string& f, const pion::platform::Vocabulary::Term& t)
00137 : field_name(f), term(t)
00138 {}
00139
00141 std::string field_name;
00142
00144 pion::platform::Vocabulary::Term term;
00145
00147 PionTimeFacet time_facet;
00148 };
00149
00151 typedef boost::shared_ptr<XMLField> XMLFieldPtr;
00152
00154 typedef PION_HASH_MAP<std::string,
00155 XMLFieldPtr,
00156 PION_HASH_STRING> FieldMap;
00157
00159 typedef std::vector<XMLFieldPtr> CurrentFormat;
00160
00161 private:
00162
00164 typedef std::istream::traits_type traits_type;
00165
00167 typedef std::basic_streambuf<
00168 std::istream::char_type,
00169 std::istream::traits_type> streambuf_type;
00170
00177 inline void mapFieldToTerm(const std::string& field,
00178 const pion::platform::Vocabulary::Term& term);
00179
00180
00181 static int xmlInputReadCallback(void* context, char* buffer, int len);
00182
00183
00184 static int xmlInputCloseCallback(void* context);
00185
00186
00188 static const std::string CONTENT_TYPE;
00189
00191 static const std::string FIELD_ELEMENT_NAME;
00192
00194 static const std::string TERM_ATTRIBUTE_NAME;
00195
00197 static const std::string EVENT_TAG_ELEMENT_NAME;
00198
00200 static const std::string DEFAULT_EVENT_TAG;
00201
00203 static const std::string EVENT_CONTAINER_TAG_ELEMENT_NAME;
00204
00206 static const std::string DEFAULT_EVENT_CONTAINER_TAG;
00207
00208
00210 std::string m_event_tag;
00211
00213 std::string m_event_container_tag;
00214
00216 FieldMap m_field_map;
00217
00219 std::map<pion::platform::Vocabulary::TermRef, XMLFieldPtr>
00220 m_XML_field_ptr_map;
00221
00223 CurrentFormat m_format;
00224
00226 bool m_flush_after_write;
00227
00229 xmlTextWriterPtr m_xml_writer;
00230
00232 xmlBufferPtr m_buf;
00233
00235 xmlTextReaderPtr m_xml_reader;
00236
00238 bool m_no_events_written;
00239
00241 bool m_first_read_attempt;
00242 };
00243
00244
00245
00246
00247 inline void XMLCodec::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 XMLFieldPtr field_ptr(new XMLField(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 }
00274
00275 #endif