You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
499 lines
16 KiB
C
499 lines
16 KiB
C
1 year ago
|
/***************************************************************************
|
||
|
* 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 <seiscomp/core/metaproperty.h>
|
||
|
|
||
|
|
||
|
namespace Seiscomp {
|
||
|
namespace DataModel {
|
||
|
|
||
|
namespace Generic {
|
||
|
|
||
|
|
||
|
template <typename T, typename U, typename F1, typename F2, int>
|
||
|
class EnumPropertyBase {};
|
||
|
|
||
|
|
||
|
//! Non-optional enum property specialization
|
||
|
template <typename T, typename U, typename F1, typename F2>
|
||
|
class EnumPropertyBase<T, U, F1, F2, 0> : 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<int>(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<U>::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 <typename T, typename U, typename F1, typename F2>
|
||
|
class EnumPropertyBase<T, U, F1, F2, 1> : 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<int>(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<U>::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 <typename A, typename T, typename U, typename F1, typename F2, int>
|
||
|
class BaseObjectPropertyBase {};
|
||
|
|
||
|
|
||
|
//! Non-optional baseobject property specialization
|
||
|
template <typename A, typename T, typename U, typename F1, typename F2>
|
||
|
class BaseObjectPropertyBase<A, T, U, F1, F2, 0> : public Core::MetaClassProperty<A> {
|
||
|
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<const Core::BaseObject*>(value);
|
||
|
}
|
||
|
catch ( boost::bad_any_cast & ) {
|
||
|
try {
|
||
|
v = boost::any_cast<Core::BaseObject*>(value);
|
||
|
}
|
||
|
catch ( boost::bad_any_cast & ) {
|
||
|
try {
|
||
|
v = boost::any_cast<const U*>(value);
|
||
|
}
|
||
|
catch ( boost::bad_any_cast & ) {
|
||
|
v = boost::any_cast<U*>(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<Core::BaseObject*>(&(const_cast<T*>(target)->*_getter)());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
F1 _setter;
|
||
|
F2 _getter;
|
||
|
};
|
||
|
|
||
|
|
||
|
//! Optional baseobject property specialization
|
||
|
template <typename A, typename T, typename U, typename F1, typename F2>
|
||
|
class BaseObjectPropertyBase<A, T, U, F1, F2, 1> : public Core::MetaClassProperty<A> {
|
||
|
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<const Core::BaseObject*>(value);
|
||
|
}
|
||
|
catch ( boost::bad_any_cast & ) {
|
||
|
try {
|
||
|
v = boost::any_cast<Core::BaseObject*>(value);
|
||
|
}
|
||
|
catch ( boost::bad_any_cast & ) {
|
||
|
try {
|
||
|
v = boost::any_cast<const typename U::value_type*>(value);
|
||
|
}
|
||
|
catch ( boost::bad_any_cast & ) {
|
||
|
v = boost::any_cast<typename U::value_type*>(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<Core::BaseObject*>(&(const_cast<T*>(target)->*_getter)());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
F1 _setter;
|
||
|
F2 _getter;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
template <typename T, typename U, typename FCOUNT, typename FOBJ, typename FADD, typename FERASE1, typename FERASE2>
|
||
|
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<size_t>((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 <typename A, typename T, typename U, typename FCOUNT, typename FOBJ, typename FADD, typename FERASE1, typename FERASE2>
|
||
|
class ArrayClassProperty : public Core::MetaClassProperty<A> {
|
||
|
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<size_t>((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 <typename T, typename U, typename F1, typename F2>
|
||
|
class EnumProperty : public Generic::EnumPropertyBase<T, U, F1, F2, Core::Generic::is_optional<U>::value> {
|
||
|
public:
|
||
|
EnumProperty(F1 setter, F2 getter)
|
||
|
: Generic::EnumPropertyBase<T, U, F1, F2, Core::Generic::is_optional<U>::value>(setter, getter) {}
|
||
|
};
|
||
|
|
||
|
|
||
|
template <class C, typename R1, typename T1, typename T2>
|
||
|
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<EnumProperty>(
|
||
|
name, type, false, false, isIndex,
|
||
|
false, isOptional, true, enumeration,
|
||
|
setter, getter);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename A, typename T, typename U, typename F1, typename F2>
|
||
|
class ObjectProperty : public Generic::BaseObjectPropertyBase<A, T, U, F1, F2, Core::Generic::is_optional<U>::value> {
|
||
|
public:
|
||
|
ObjectProperty(F1 setter, F2 getter)
|
||
|
: Generic::BaseObjectPropertyBase<A, T, U, F1, F2, Core::Generic::is_optional<U>::value>(setter, getter) {}
|
||
|
};
|
||
|
|
||
|
|
||
|
template <typename A, typename C, typename R1, typename T1, typename T2>
|
||
|
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<T1>::type
|
||
|
>::type
|
||
|
>::type
|
||
|
>::type T;
|
||
|
|
||
|
Core::MetaPropertyHandle h = Core::MetaPropertyHandle(new ObjectProperty<A, C, T, R1 (C::*)(T1), T2 (C::*)()>(setter, getter));
|
||
|
h->setInfo(name, type, false, true, isIndex, isReference, isOptional, false, nullptr);
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
template <template <typename, typename, typename, typename, typename, typename, typename> class P,
|
||
|
class C, typename T>
|
||
|
Core::MetaPropertyHandle createArrayProperty(const std::string& name, const std::string& type,
|
||
|
size_t (C::*counter)() const,
|
||
|
T* (C::*getter)(size_t) const,
|
||
|
bool (C::*adder)(T *),
|
||
|
bool (C::*indexRemove)(size_t),
|
||
|
bool (C::*ptrRemove)(T *)) {
|
||
|
Core::MetaPropertyHandle h = Core::MetaPropertyHandle(
|
||
|
new P<C, T, size_t (C::*)() const, T* (C::*)(size_t i) const, bool (C::*)(T *), bool (C::*)(size_t i), bool (C::*)(T *)>(counter, getter ,adder, indexRemove, ptrRemove));
|
||
|
h->setInfo(name, type, true, true, false, false, false, false, nullptr);
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename A, template <typename ,typename, typename, typename, typename, typename, typename, typename> class P,
|
||
|
class C, typename T>
|
||
|
Core::MetaPropertyHandle createArrayClassProperty(const std::string& name,
|
||
|
const std::string& type,
|
||
|
size_t (C::*counter)() const,
|
||
|
T* (C::*getter)(size_t) const,
|
||
|
bool (C::*adder)(T *),
|
||
|
bool (C::*indexRemove)(size_t),
|
||
|
bool (C::*ptrRemove)(T *)) {
|
||
|
Core::MetaPropertyHandle h = Core::MetaPropertyHandle(
|
||
|
new P<A, C, T, size_t (C::*)() const, T* (C::*)(size_t i) const, bool (C::*)(T *), bool (C::*)(size_t i), bool (C::*)(T *)>(counter, getter ,adder, indexRemove, ptrRemove));
|
||
|
h->setInfo(name, type, true, true, false, false, false, false, nullptr);
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename C, typename T>
|
||
|
Core::MetaPropertyHandle arrayObjectProperty(
|
||
|
const std::string& name, const std::string& type,
|
||
|
size_t (C::*counter)() const,
|
||
|
T* (C::*getter)(size_t) const,
|
||
|
bool (C::*adder)(T *),
|
||
|
bool (C::*indexRemove)(size_t),
|
||
|
bool (C::*ptrRemove)(T *)
|
||
|
) {
|
||
|
return createArrayProperty<Generic::ArrayProperty>(name, type, counter, getter, adder, indexRemove, ptrRemove);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename A, typename C, typename T>
|
||
|
Core::MetaPropertyHandle arrayClassProperty(
|
||
|
const std::string& name, const std::string& type,
|
||
|
size_t (C::*counter)() const,
|
||
|
T* (C::*getter)(size_t) const,
|
||
|
bool (C::*adder)(T *),
|
||
|
bool (C::*indexRemove)(size_t),
|
||
|
bool (C::*ptrRemove)(T *)
|
||
|
) {
|
||
|
return createArrayClassProperty<A, Generic::ArrayClassProperty>(name, type, counter, getter, adder, indexRemove, ptrRemove);
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|