/*************************************************************************** * 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_DATAMODEL_METADATA_H__ #define SEISCOMP_DATAMODEL_METADATA_H__ #include namespace Seiscomp { namespace DataModel { namespace Generic { template class EnumPropertyBase {}; //! Non-optional enum property specialization template class EnumPropertyBase : public Core::MetaProperty { public: EnumPropertyBase(F1 setter, F2 getter) : _setter(setter), _getter(getter) {} bool write(Core::BaseObject *object, Core::MetaValue value) const { T *target = T::Cast(object); if ( !target ) return false; U tmp; if ( !tmp.fromInt(boost::any_cast(value)) ) return false; (target->*_setter)(tmp); return true; } bool writeString(Core::BaseObject *object, const std::string &value) const { T *target = T::Cast(object); if ( !target ) return false; typename Core::Generic::remove_optional::type tmp; if ( !tmp.fromString(value.c_str()) ) return false; (target->*_setter)(tmp); return true; } Core::MetaValue read(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_getter)().toInt(); } std::string readString(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_getter)().toString(); } private: F1 _setter; F2 _getter; }; //! Optional enum property specialization template class EnumPropertyBase : public Core::MetaProperty { public: EnumPropertyBase(F1 setter, F2 getter) : _setter(setter), _getter(getter) {} bool write(Core::BaseObject *object, Core::MetaValue value) const { T *target = T::Cast(object); if ( !target ) return false; if ( value.empty() ) (target->*_setter)(Core::None); else { typename U::value_type tmp; if ( !tmp.fromInt(boost::any_cast(value)) ) return false; (target->*_setter)(tmp); } return true; } bool writeString(Core::BaseObject *object, const std::string &value) const { T *target = T::Cast(object); if ( !target ) return false; if ( value.empty() ) (target->*_setter)(Core::None); else { typename Core::Generic::remove_optional::type tmp; if ( !tmp.fromString(value.c_str()) ) return false; (target->*_setter)(tmp); } return true; } Core::MetaValue read(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_getter)().toInt(); } std::string readString(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_getter)().toString(); } private: F1 _setter; F2 _getter; }; template class BaseObjectPropertyBase {}; //! Non-optional baseobject property specialization template class BaseObjectPropertyBase : public Core::MetaClassProperty { public: BaseObjectPropertyBase(F1 setter, F2 getter) : _setter(setter), _getter(getter) {} bool write(Core::BaseObject *object, Core::MetaValue value) const { T *target = T::Cast(object); if ( !target ) return false; const Core::BaseObject *v; try { v = boost::any_cast(value); } catch ( boost::bad_any_cast & ) { try { v = boost::any_cast(value); } catch ( boost::bad_any_cast & ) { try { v = boost::any_cast(value); } catch ( boost::bad_any_cast & ) { v = boost::any_cast(value); } } } if ( v == nullptr ) throw Core::GeneralException("value must not be nullptr"); const U *uv = U::ConstCast(v); if ( uv == nullptr ) throw Core::GeneralException("value has wrong classtype"); (target->*_setter)(*uv); return true; } Core::MetaValue read(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return static_cast(&(const_cast(target)->*_getter)()); } private: F1 _setter; F2 _getter; }; //! Optional baseobject property specialization template class BaseObjectPropertyBase : public Core::MetaClassProperty { public: BaseObjectPropertyBase(F1 setter, F2 getter) : _setter(setter), _getter(getter) {} bool write(Core::BaseObject *object, Core::MetaValue value) const { T *target = T::Cast(object); if ( !target ) return false; if ( value.empty() ) (target->*_setter)(Core::None); else { const Core::BaseObject *v; try { v = boost::any_cast(value); } catch ( boost::bad_any_cast & ) { try { v = boost::any_cast(value); } catch ( boost::bad_any_cast & ) { try { v = boost::any_cast(value); } catch ( boost::bad_any_cast & ) { v = boost::any_cast(value); } } } if ( v == nullptr ) throw Core::GeneralException("value must not be nullptr"); const typename U::value_type *uv = U::value_type::ConstCast(v); if ( uv == nullptr ) throw Core::GeneralException("value has wrong classtype"); (target->*_setter)(*uv); return true; } return true; } Core::MetaValue read(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return static_cast(&(const_cast(target)->*_getter)()); } private: F1 _setter; F2 _getter; }; template class ArrayProperty : public Core::MetaProperty { public: ArrayProperty(FCOUNT countObjects, FOBJ getObj, FADD addObj, FERASE1 eraseObjIndex, FERASE2 eraseObjPointer) : _countObjects(countObjects), _getObj(getObj), _addObj(addObj), _eraseObjIndex(eraseObjIndex), _eraseObjPointer(eraseObjPointer) {} size_t arrayElementCount(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return static_cast((target->*_countObjects)()); } Core::BaseObject *arrayObject(Core::BaseObject *object, int i) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_getObj)(i); } bool arrayAddObject(Core::BaseObject *object, Core::BaseObject *ch) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); U *child = U::Cast(ch); if ( !child ) throw Core::GeneralException("wrong child class type"); return (target->*_addObj)(child); } bool arrayRemoveObject(Core::BaseObject *object, int i) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_eraseObjIndex)(i); } bool arrayRemoveObject(Core::BaseObject *object, Core::BaseObject *ch) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); U *child = U::Cast(ch); if ( !child ) throw Core::GeneralException("wrong child class type"); return (target->*_eraseObjPointer)(child); } Core::BaseObject *createClass() const { return U::Create(); } private: FCOUNT _countObjects; FOBJ _getObj; FADD _addObj; FERASE1 _eraseObjIndex; FERASE2 _eraseObjPointer; }; template class ArrayClassProperty : public Core::MetaClassProperty { public: ArrayClassProperty(FCOUNT countObjects, FOBJ getObj, FADD addObj, FERASE1 eraseObjIndex, FERASE2 eraseObjPointer) : _countObjects(countObjects), _getObj(getObj), _addObj(addObj), _eraseObjIndex(eraseObjIndex), _eraseObjPointer(eraseObjPointer) {} size_t arrayElementCount(const Core::BaseObject *object) const { const T *target = T::ConstCast(object); if ( !target ) throw Core::GeneralException("invalid object"); return static_cast((target->*_countObjects)()); } Core::BaseObject *arrayObject(Core::BaseObject *object, int i) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_getObj)(i); } bool arrayAddObject(Core::BaseObject *object, Core::BaseObject *ch) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); U *child = U::Cast(ch); if ( !child ) throw Core::GeneralException("wrong child class type"); return (target->*_addObj)(child); } bool arrayRemoveObject(Core::BaseObject *object, int i) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); return (target->*_eraseObjIndex)(i); } bool arrayRemoveObject(Core::BaseObject *object, Core::BaseObject *ch) const { T *target = T::Cast(object); if ( !target ) throw Core::GeneralException("invalid object"); U *child = U::Cast(ch); if ( !child ) throw Core::GeneralException("wrong child class type"); return (target->*_eraseObjPointer)(child); } private: FCOUNT _countObjects; FOBJ _getObj; FADD _addObj; FERASE1 _eraseObjIndex; FERASE2 _eraseObjPointer; }; } template class EnumProperty : public Generic::EnumPropertyBase::value> { public: EnumProperty(F1 setter, F2 getter) : Generic::EnumPropertyBase::value>(setter, getter) {} }; template Core::MetaPropertyHandle enumProperty( const std::string& name, const std::string& type, bool isIndex, bool isOptional, const Core::MetaEnum *enumeration, R1 (C::*setter)(T1), T2 (C::*getter)() const) { return Core::createProperty( name, type, false, false, isIndex, false, isOptional, true, enumeration, setter, getter); } template class ObjectProperty : public Generic::BaseObjectPropertyBase::value> { public: ObjectProperty(F1 setter, F2 getter) : Generic::BaseObjectPropertyBase::value>(setter, getter) {} }; template Core::MetaPropertyHandle objectProperty( const std::string& name, const std::string& type, bool isIndex, bool isReference, bool isOptional, R1 (C::*setter)(T1), T2 (C::*getter)()) { typedef typename std::remove_const< typename std::remove_cv< typename std::remove_pointer< typename std::remove_reference::type >::type >::type >::type T; Core::MetaPropertyHandle h = Core::MetaPropertyHandle(new ObjectProperty(setter, getter)); h->setInfo(name, type, false, true, isIndex, isReference, isOptional, false, nullptr); return h; } template