/*************************************************************************** * Copyright (C) gempa GmbH * * All rights reserved. * * Contact: gempa GmbH (seiscomp-dev@gempa.de) * * * * GNU Affero General Public License Usage * * This file may be used under the terms of the GNU Affero * * Public License version 3.0 as published by the Free Software Foundation * * and appearing in the file LICENSE included in the packaging of this * * file. Please review the following information to ensure the GNU Affero * * Public License version 3.0 requirements will be met: * * https://www.gnu.org/licenses/agpl-3.0.html. * * * * Other Usage * * Alternatively, this file may be used in accordance with the terms and * * conditions contained in a signed written agreement between you and * * gempa GmbH. * ***************************************************************************/ #ifndef SEISCOMP_IO_XMLHANDLER_H #define SEISCOMP_IO_XMLHANDLER_H #include #include #include #include #include namespace Seiscomp { namespace IO { namespace XML { typedef std::vector ChildList; typedef std::set TagSet; struct SC_SYSTEM_CORE_API NodeHandler; class SC_SYSTEM_CORE_API OutputHandler { public: virtual ~OutputHandler(); virtual void handle(Core::BaseObject *, const char *tag, const char *ns, NodeHandler * = nullptr) = 0; virtual bool openElement(const char *name, const char *ns) = 0; virtual void addAttribute(const char *name, const char *ns, const char *value) = 0; virtual void closeElement(const char *name, const char *ns) = 0; virtual void put(const char *content) = 0; }; class SC_SYSTEM_CORE_API MemberNodeHandler; //! A NodeHandler handles nodes describing a class. struct SC_SYSTEM_CORE_API NodeHandler { virtual ~NodeHandler(); virtual bool init(Core::BaseObject *obj, void *n, TagSet &mandatoryTags) { return false; } // When called, object, next and newInstance are preset by the caller // object = nullptr // next = noneReader // newInstance = false // memberHandler = nullptr virtual std::string value(Core::BaseObject *obj) { return ""; } virtual bool put(Core::BaseObject *obj, const char *tag, const char *ns, OutputHandler *output) = 0; virtual bool get(Core::BaseObject *obj, void *n) { return false; } virtual bool finalize(Core::BaseObject *obj, ChildList *) { return false; } std::string content(void *n) const; bool equalsTag(void *n, const char *, const char *) const; //! Reset all members to default values void propagate(Core::BaseObject *o, bool ni, bool opt); Core::BaseObject *object; NodeHandler *childHandler; MemberNodeHandler *memberHandler; bool newInstance; bool isOptional; bool isAnyType; static bool strictNsCheck; }; //! A MemberHandler handles setting of members of a class. Members can //! be optional, mandatory and childs. struct SC_SYSTEM_CORE_API MemberHandler { virtual ~MemberHandler(); virtual std::string value(Core::BaseObject *obj) = 0; virtual bool put(Core::BaseObject *object, const char *tag, const char *ns, bool opt, OutputHandler *output, NodeHandler *h); //! Get a "node" to the member of an object. virtual bool get(Core::BaseObject *object, void *node, NodeHandler *h) = 0; //! Finalizes the read member object (can be nullptr). virtual bool finalize(Core::BaseObject *parent, Core::BaseObject *member) { return true; } }; class PropertyHandler : public MemberHandler { public: PropertyHandler(const Core::MetaProperty *prop) : _property(prop) {} std::string value(Core::BaseObject *obj) { try { return _property->readString(obj); } catch ( ... ) { return ""; } } bool put(Core::BaseObject *object, const char *tag, const char *ns, bool opt, OutputHandler *output, NodeHandler *h) { if ( _property->isClass() ) { try { output->handle(boost::any_cast(_property->read(object)), tag, ns); return true; } catch ( ... ) {} } else return MemberHandler::put(object, tag, ns, opt, output, h); return false; } bool get(Core::BaseObject *object, void *, NodeHandler *); bool finalize(Core::BaseObject *parent, Core::BaseObject *member); private: const Core::MetaProperty *_property; }; class ChildPropertyHandler : public MemberHandler { public: ChildPropertyHandler(const Core::MetaProperty *prop) : _property(prop) {} std::string value(Core::BaseObject *obj) { return ""; } bool put(Core::BaseObject *object, const char *tag, const char *ns, bool opt, OutputHandler *output, NodeHandler *h) { size_t count = _property->arrayElementCount(object); for ( size_t i = 0; i < count; ++i ) { output->handle(_property->arrayObject(object, i), tag, ns); } return true; } bool get(Core::BaseObject *object, void *, NodeHandler *h) { h->propagate(_property->createClass(), true, true); return true; } bool finalize(Core::BaseObject *parent, Core::BaseObject *child) { if ( child ) return _property->arrayAddObject(parent, child); return false; } private: const Core::MetaProperty *_property; }; struct SC_SYSTEM_CORE_API TypeHandler { TypeHandler(NodeHandler *nh) : nodeHandler(nh) {} virtual ~TypeHandler(); virtual Core::BaseObject *createClass() = 0; virtual const char *className() = 0; NodeHandler *nodeHandler; }; struct SC_SYSTEM_CORE_API TypeNameHandler : public TypeHandler { TypeNameHandler(NodeHandler *nh, const char *cn) : TypeHandler(nh), classname(cn) {} Core::BaseObject *createClass() { return Core::ClassFactory::Create(classname.c_str()); } const char *className() { return classname.c_str(); } std::string classname; }; template struct TypeStaticHandler : public TypeHandler { TypeStaticHandler(NodeHandler *nh) : TypeHandler(nh) {} Core::BaseObject *createClass() { return new T(); } const char *className() { return T::ClassName(); } }; struct SC_SYSTEM_CORE_API TypeMap { struct Tag { Tag(); Tag(const std::string &, const std::string &); bool operator<(const Tag &other) const; std::string name; std::string ns; }; // Maps a tag to a classname typedef std::map TagMap; // Maps a tag without namespace to a classname typedef std::map RawTagMap; // Maps a classname to a tag typedef std::map ClassMap; // Maps a classname to a handler typedef std::map HandlerMap; TagMap tags; RawTagMap tagsWithoutNs; ClassMap classes; HandlerMap handlers; TypeMap(); ~TypeMap(); void registerMapping(const char *tag, const char *ns, const char *classname, NodeHandler *handler); template void registerMapping(const char *tag, const char *ns, NodeHandler *handler); const char *getClassname(const char *tag, const char *ns, bool strictNsCheck); const Tag *getTag(const char *classname); NodeHandler *getHandler(const char *classname); Core::BaseObject *createClass(const char *classname); }; struct SC_SYSTEM_CORE_API MemberNodeHandler { MemberNodeHandler() {} MemberNodeHandler(const char *t, const char *ns, bool opt) : tag(t), nameSpace(ns), optional(opt) {} MemberNodeHandler(const char *t, const char *ns, bool opt, MemberHandler *s); std::string value(Core::BaseObject *obj) { return setter->value(obj); } bool put(Core::BaseObject *obj, OutputHandler *output, NodeHandler *h); bool get(Core::BaseObject *obj, void *, NodeHandler *h); bool finalize(Core::BaseObject *parent, Core::BaseObject *child); std::string tag; std::string nameSpace; bool optional; std::shared_ptr setter; }; struct SC_SYSTEM_CORE_API NoneHandler : public NodeHandler { bool put(Core::BaseObject *obj, const char *tag, const char *ns, OutputHandler *output); bool get(Core::BaseObject *obj, void *n); }; struct SC_SYSTEM_CORE_API GenericHandler : public NodeHandler { bool put(Core::BaseObject *obj, const char *tag, const char *ns, OutputHandler *output); bool get(Core::BaseObject *, void *n); TypeMap *mapper; }; struct SC_SYSTEM_CORE_API ClassHandler : public NodeHandler { typedef std::list MemberList; typedef std::list MemberRefList; enum Location { Attribute, Element, CDATA }; enum Type { Mandatory = 0, Optional = 1 }; ClassHandler() { cdataUsed = false; } template void addMember(const char *t, const char *ns, Type opt, Location l, R (C::*s)(T)); template void addMember(const char *t, const char *ns, Type opt, R (C::*s)(T1), T2 (C::*g)()); void addMember(const char *t, const char *ns, Type opt, Location l, MemberHandler *s); void addChild(const char *t, const char *ns, MemberHandler *s); bool init(Core::BaseObject *obj, void *n, TagSet &mandatoryTags); bool get(Core::BaseObject *obj, void *n); bool put(Core::BaseObject *obj, const char *tag, const char *ns, OutputHandler *output); MemberRefList orderedMembers; MemberList attributes; MemberList elements; MemberList childs; MemberNodeHandler cdata; bool cdataUsed; }; template struct TypedClassHandler : public ClassHandler { void addProperty(const char *t, const char *ns, Type opt, Location l, const Core::MetaProperty *prop); void addProperty(const char *t, const char *ns, Type opt, Location l, const char *property); void addChildProperty(const char *t, const char *ns, const char *property); }; #include } } } #endif