OpenSceneGraph/include/osgIntrospection/Reflector
2005-04-04 13:50:07 +00:00

843 lines
28 KiB
Plaintext

#ifndef OSGINTROSPECTION_REFLECTOR_
#define OSGINTROSPECTION_REFLECTOR_
#include <osgIntrospection/Reflection>
#include <osgIntrospection/Type>
#include <osgIntrospection/Value>
#include <osgIntrospection/PropertyInfo>
#include <osgIntrospection/MethodInfo>
#include <osgIntrospection/ConstructorInfo>
#include <osgIntrospection/InstanceCreator>
#include <osgIntrospection/ReaderWriter>
#include <osgIntrospection/TypedConstructorInfo>
#include <osgIntrospection/Comparator>
#include <string>
#include <sstream>
#include <iterator>
namespace osgIntrospection
{
class CustomAttribute;
class ReaderWriter;
/// A Reflector is a proxy class that is used to create a new description
/// of a given type. If the type to be described is simple and doesn't
/// require additional details such as properties and methods, it can be
/// reflected by simply creating a global instance of one of the classes
/// derived from Reflector, for example ValueReflector. Other types may
/// need further information and therefore it could be necessary to create
/// a new subclass of Reflector or extend one of the existing subclasses.
/// The reflected type can be set by calling Reflector's protected
/// methods.
///
/// NOTE: when you create a Reflector for type T, it will automatically
/// create descriptions for types T* and const T*. You should NEVER
/// create reflectors for pointer types explicitely.
///
template<typename T>
class Reflector
{
public:
typedef T reflected_type;
typedef Reflector<T> inherited;
/// Virtual destructor.
virtual ~Reflector() {}
protected:
/// Direct initialization constructor. Parameter 'name' is the name
/// of the type being reflected and 'ns' is its namespace.
Reflector(const std::string &name, const std::string &ns, bool abstract = false);
/// Direct initialization constructor. Parameter 'qname' is the
/// fully-qualified name of the type being reflected, i.e. containing
/// both the namespace and the name (separated by "::").
Reflector(const std::string &qname, bool abstract = false);
protected:
/// Returns the Type object being described.
Type *getType() { return type_; }
/// Declares a new base type for the current type.
void addBaseType(const Type &type);
/// Sets the comparator object for the current type.
void setComparator(const Comparator *cmp);
/// Adds a property description to the current type.
PropertyInfo *addProperty(PropertyInfo *pi);
/// Adds a method description to the current type.
MethodInfo *addMethod(MethodInfo *mi);
/// Adds an enumeration label to the current type.
void addEnumLabel(int v, const std::string &label, bool strip_namespace = true);
/// Adds a constructor description to the current type.
/// As soon as a constructor is added through this method,
/// the automatically-generated default constructor is
/// removed.
ConstructorInfo *addConstructor(ConstructorInfo *ci);
/// Returns a string containing the qualified version of 'name'.
std::string qualifyName(const std::string name) const;
/// Adds a custom attribute to the type being described.
CustomAttributeProvider *addAttribute(const CustomAttribute *attrib);
/// Sets the current type's ReaderWriter object.
void setReaderWriter(const ReaderWriter *rw);
private:
struct PtrConstructor: ConstructorInfo
{
PtrConstructor(const Type *pt)
: ConstructorInfo(*pt, ParameterInfoList())
{
}
Value createInstance(ValueList &) const { T* x = 0; return x; }
};
struct ConstPtrConstructor: ConstructorInfo
{
ConstPtrConstructor(const Type *pt)
: ConstructorInfo(*pt, ParameterInfoList())
{
}
Value createInstance(ValueList &) const { const T *x = 0; return x; }
};
void init();
static std::string purify(const std::string &s);
static void split_qualified_name(const std::string &q, std::string &n, std::string &ns);
typedef std::vector<MethodInfo *> TempMethodList;
TempMethodList temp_methods_;
Type *type_;
};
/// This reflector ought to be used to describe types that can be
/// created on the stack. Such types are for example int, double,
/// std::string, or other (possibly small) user-defined structs or
/// classes. The instance creator associated to types created through
/// this reflector will create Value objects whose internal type is T.
template<typename T>
struct ValueReflector: Reflector<T>
{
typedef ValueReflector<T> inherited;
typedef ValueInstanceCreator<typename Reflector<T>::reflected_type> instance_creator_type;
ValueReflector(const std::string &name, const std::string &ns)
: Reflector<T>(name, ns, false)
{
}
ValueReflector(const std::string &qname)
: Reflector<T>(qname, false)
{
}
};
/// This reflector is to be used to describe abstract types that can't
/// be instantiated. For this reason a DummyInstanceCreator is used in
/// order to avoid compiler errors.
template<typename T>
struct AbstractObjectReflector: Reflector<T>
{
typedef AbstractObjectReflector<T> inherited;
typedef DummyInstanceCreator<typename Reflector<T>::reflected_type> instance_creator_type;
AbstractObjectReflector(const std::string &name, const std::string &ns)
: Reflector<T>(name, ns, true)
{
}
AbstractObjectReflector(const std::string &qname)
: Reflector<T>(qname, true)
{
}
};
/// This reflector is to be used to describe types that ought to be
/// created on the heap. Such types are for example all classes derived
/// from osg::Referenced. The instance creator associated to types
/// created through this reflector will create Value objects whose
/// internal type is T*.
template<typename T>
struct ObjectReflector: Reflector<T>
{
typedef ObjectReflector<T> inherited;
typedef ObjectInstanceCreator<typename Reflector<T>::reflected_type> instance_creator_type;
ObjectReflector(const std::string &name, const std::string &ns)
: Reflector<T>(name, ns, false)
{
}
ObjectReflector(const std::string &qname)
: Reflector<T>(qname, false)
{
}
};
/// This reflector is a ValueReflector that should be used to define
/// types that can be read and written from/to streams using the <<
/// and >> operators. A StdReaderWriter is assigned by default.
template<typename T>
struct AtomicValueReflector: ValueReflector<T>
{
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
AtomicValueReflector(const std::string &name, const std::string &ns)
: ValueReflector<T>(name, ns)
{
setReaderWriter(new StdReaderWriter<T>);
setComparator(new PartialOrderComparator<T>);
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
}
AtomicValueReflector(const std::string &qname)
: ValueReflector<T>(qname)
{
setReaderWriter(new StdReaderWriter<T>);
setComparator(new PartialOrderComparator<T>);
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
}
};
/// This reflector is a ValueReflector that should be used to define
/// enumerations. It assigns an EnumReaderWriter by default.
template<typename T>
struct EnumReflector: ValueReflector<T>
{
typedef EnumReflector<T> inherited;
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
EnumReflector(const std::string &name, const std::string &ns)
: ValueReflector<T>(name, ns)
{
setReaderWriter(new EnumReaderWriter<T>);
setComparator(new TotalOrderComparator<T>);
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
}
EnumReflector(const std::string &qname)
: ValueReflector<T>(qname)
{
setReaderWriter(new EnumReaderWriter<T>);
setComparator(new TotalOrderComparator<T>);
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
}
};
/// This class allows to define the means for reflecting STL containers
/// such as std::deque and std::vector.
template<typename T, typename VT>
struct StdVectorReflector: ValueReflector<T>
{
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
struct Getter: PropertyGetter
{
virtual Value get(Value &instance, int i) const
{
T &ctr = variant_cast<T &>(instance);
return ctr.at(i);
}
virtual Value get(const Value &instance, int i) const
{
const T &ctr = variant_cast<const T &>(instance);
return ctr.at(i);
}
};
struct Setter: PropertySetter
{
virtual void set(Value &instance, int i, const Value &v) const
{
T &ctr = variant_cast<T &>(instance);
ctr.at(i) = variant_cast<const typename T::value_type &>(v);
}
};
struct Counter: PropertyCounter
{
virtual int count(const Value &instance) const
{
const T &ctr = variant_cast<const T &>(instance);
return static_cast<int>(ctr.size());
}
};
struct Adder: PropertyAdder
{
virtual void add(Value &instance, const Value &v) const
{
T &ctr = variant_cast<T &>(instance);
ctr.push_back(variant_cast<const typename T::value_type &>(v));
}
};
struct Remover: PropertyRemover
{
virtual void remove(Value &instance, int i) const
{
T &ctr = variant_cast<T &>(instance);
typename T::iterator j=ctr.begin();
std::advance(j, i);
ctr.erase(j);
}
};
StdVectorReflector(const std::string &name): ValueReflector<T>(name)
{
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
PropertyInfo *pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Items", 0, 0, 0, 0, 0);
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
pi->addAttribute(new CustomPropertySetAttribute(new Setter));
pi->addAttribute(new CustomPropertyCountAttribute(new Counter));
pi->addAttribute(new CustomPropertyAddAttribute(new Adder));
pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover));
if (typeid(VT).before(typeid(typename T::value_type)) ||
typeid(typename T::value_type).before(typeid(VT)))
{
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
}
this->addProperty(pi);
}
};
/// This class allows to define the means for reflecting STL containers
/// such as std::set and std::multiset.
template<typename T, typename VT>
struct StdSetReflector: ValueReflector<T>
{
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
struct Getter: PropertyGetter
{
virtual Value get(Value &instance, int i) const
{
T &ctr = variant_cast<T &>(instance);
typename T::iterator j=ctr.begin();
std::advance(j, i);
return *j;
}
virtual Value get(const Value &instance, int i) const
{
const T &ctr = variant_cast<const T &>(instance);
typename T::const_iterator j=ctr.begin();
std::advance(j, i);
return *j;
}
};
struct Counter: PropertyCounter
{
virtual int count(const Value &instance) const
{
const T &ctr = variant_cast<const T &>(instance);
return static_cast<int>(ctr.size());
}
};
struct Adder: PropertyAdder
{
virtual void add(Value &instance, const Value &v) const
{
T &ctr = variant_cast<T &>(instance);
ctr.insert(variant_cast<const typename T::value_type &>(v));
}
};
struct Remover: PropertyRemover
{
virtual void remove(Value &instance, int i) const
{
T &ctr = variant_cast<T &>(instance);
typename T::iterator j=ctr.begin();
std::advance(j, i);
ctr.erase(j);
}
};
StdSetReflector(const std::string &name): ValueReflector<T>(name)
{
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
PropertyInfo *pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Items", 0, 0, 0, 0, 0);
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
pi->addAttribute(new CustomPropertyCountAttribute(new Counter));
pi->addAttribute(new CustomPropertyAddAttribute(new Adder));
pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover));
if (typeid(VT).before(typeid(typename T::value_type)) ||
typeid(typename T::value_type).before(typeid(VT)))
{
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
}
this->addProperty(pi);
}
};
/// This class allows to define the means for reflecting STL containers
/// that cannot be indexed directly, such as std::list.
template<typename T, typename VT>
struct StdListReflector: ValueReflector<T>
{
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
struct Getter: PropertyGetter
{
virtual Value get(Value &instance, int i) const
{
T &ctr = variant_cast<T &>(instance);
typename T::iterator j=ctr.begin();
std::advance(j, i);
return *j;
}
virtual Value get(const Value &instance, int i) const
{
const T &ctr = variant_cast<const T &>(instance);
typename T::const_iterator j=ctr.begin();
std::advance(j, i);
return *j;
}
};
struct Setter: PropertySetter
{
virtual void set(Value &instance, int i, const Value &v) const
{
T &ctr = variant_cast<T &>(instance);
typename T::iterator j=ctr.begin();
std::advance(j, i);
*j = variant_cast<const typename T::value_type &>(v);
}
};
struct Counter: PropertyCounter
{
virtual int count(const Value &instance) const
{
const T &ctr = variant_cast<const T &>(instance);
return static_cast<int>(ctr.size());
}
};
struct Adder: PropertyAdder
{
virtual void add(Value &instance, const Value &v) const
{
T &ctr = variant_cast<T &>(instance);
ctr.push_back(variant_cast<const typename T::value_type &>(v));
}
};
struct Remover: PropertyRemover
{
virtual void remove(Value &instance, int i) const
{
T &ctr = variant_cast<T &>(instance);
typename T::iterator j=ctr.begin();
std::advance(j, i);
ctr.erase(j);
}
};
StdListReflector(const std::string &name): ValueReflector<T>(name)
{
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
PropertyInfo *pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Items", 0, 0, 0, 0, 0);
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
pi->addAttribute(new CustomPropertySetAttribute(new Setter));
pi->addAttribute(new CustomPropertyCountAttribute(new Counter));
pi->addAttribute(new CustomPropertyAddAttribute(new Adder));
pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover));
if (typeid(VT).before(typeid(typename T::value_type)) ||
typeid(typename T::value_type).before(typeid(VT)))
{
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
}
this->addProperty(pi);
}
};
/// This class allows to define the means for reflecting STL associative
/// containers which hold pairs of key+value, such as std::map.
template<typename T, typename IT, typename VT>
struct StdMapReflector: ValueReflector<T>
{
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
typedef typename T::key_type key_type;
typedef typename T::mapped_type mapped_type;
struct Getter: PropertyGetter
{
virtual Value get(Value &instance, const ValueList &indices) const
{
T& ctr = variant_cast<T &>(instance);
const key_type& key = variant_cast<const key_type &>(indices.front());
iterator i = ctr.find(key);
if (i == ctr.end()) return Value();
return i->second;
}
virtual Value get(const Value &instance, const ValueList &indices) const
{
const T& ctr = variant_cast<const T &>(instance);
const key_type& key = variant_cast<const key_type &>(indices.front());
const_iterator i = ctr.find(key);
if (i == ctr.end()) return Value();
return i->second;
}
};
struct Setter: PropertySetter
{
virtual void set(Value &instance, const ValueList &indices, const Value &v) const
{
T &ctr = variant_cast<T &>(instance);
ctr.insert(std::make_pair(variant_cast<const key_type &>(indices.front()), variant_cast<const mapped_type &>(v)));
}
};
struct Indexer: IndexInfo
{
ParameterInfoList params_;
const Type &itype_;
Indexer()
: itype_(typeof(IT))
{
params_.push_back(new ParameterInfo("key", typeof(key_type), 0, ParameterInfo::IN));
}
virtual ~Indexer()
{
delete params_.front();
}
virtual const ParameterInfoList &getIndexParameters() const
{
return params_;
}
virtual void getIndexValueSet(int /*whichindex*/, const Value &instance, ValueList &values) const
{
const T &ctr = variant_cast<const T &>(instance);
for (const_iterator i=ctr.begin();
i!=ctr.end();
++i)
{
values.push_back(Value(i->first).convertTo(itype_));
}
}
};
StdMapReflector(const std::string &name): ValueReflector<T>(name)
{
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
PropertyInfo *pi = new PropertyInfo(typeof(T), typeof(typename T::mapped_type), "Items", 0, 0);
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
pi->addAttribute(new CustomPropertySetAttribute(new Setter));
pi->addAttribute(new CustomIndexAttribute(new Indexer));
if (typeid(VT).before(typeid(typename T::mapped_type)) ||
typeid(typename T::mapped_type).before(typeid(VT)))
{
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
}
this->addProperty(pi);
}
};
template<typename T, typename PT1, typename PT2>
struct StdPairReflector: ValueReflector<T>
{
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
struct Accessor: PropertyGetter, PropertySetter
{
Accessor(int i): i_(i) {}
virtual Value get(const Value &instance) const
{
switch (i_)
{
case 0: return variant_cast<T &>(instance).first;
case 1: return variant_cast<T &>(instance).second;
default: return Value();
}
}
virtual Value get(Value &instance) const
{
switch (i_)
{
case 0: return variant_cast<const T &>(instance).first;
case 1: return variant_cast<const T &>(instance).second;
default: return Value();
}
}
virtual void set(const Value &instance, const Value &v) const
{
T &ctr = variant_cast<T &>(instance);
switch (i_)
{
case 0: ctr.first = variant_cast<const typename T::first_type &>(v); break;
case 1: ctr.second = variant_cast<const typename T::second_type &>(v); break;
}
}
int i_;
};
StdPairReflector(const std::string &name): ValueReflector<T>(name)
{
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
PropertyInfo *pi1 = new PropertyInfo(typeof(T), typeof(typename T::first_type), "first", 0, 0);
pi1->addAttribute(new CustomPropertyGetAttribute(new Accessor(0)));
pi1->addAttribute(new CustomPropertySetAttribute(new Accessor(0)));
if (typeid(PT1).before(typeid(typename T::first_type)) ||
typeid(typename T::first_type).before(typeid(PT1)))
pi1->addAttribute(new PropertyTypeAttribute(typeof(PT1)));
this->addProperty(pi1);
PropertyInfo *pi2 = new PropertyInfo(typeof(T), typeof(typename T::second_type), "second", 0, 0);
pi2->addAttribute(new CustomPropertyGetAttribute(new Accessor(1)));
pi2->addAttribute(new CustomPropertySetAttribute(new Accessor(1)));
if (typeid(PT2).before(typeid(typename T::second_type)) ||
typeid(typename T::second_type).before(typeid(PT2)))
pi2->addAttribute(new PropertyTypeAttribute(typeof(PT2)));
this->addProperty(pi2);
}
};
// TEMPLATE METHODS
template<typename T>
Reflector<T>::Reflector(const std::string &name, const std::string &ns, bool abstract)
: type_(Reflection::getOrRegisterType(typeid(T), true))
{
if (!type_->name_.empty())
type_->aliases_.push_back(ns.empty()? purify(name): purify(ns+"::"+name));
else
{
type_->name_ = purify(name);
type_->namespace_ = purify(ns);
}
type_->is_abstract_ = abstract;
init();
}
template<typename T>
Reflector<T>::Reflector(const std::string &qname, bool abstract)
: type_(Reflection::getOrRegisterType(typeid(T), true))
{
if (!type_->name_.empty())
type_->aliases_.push_back(purify(qname));
else
{
split_qualified_name(purify(qname), type_->name_, type_->namespace_);
}
type_->is_abstract_ = abstract;
init();
}
template<typename T>
void Reflector<T>::init()
{
// pointer type
if (!type_->pointed_type_)
{
Type *ptype = Reflection::getOrRegisterType(typeid(T*), true);
ptype->name_ = type_->name_;
ptype->namespace_ = type_->namespace_;
ptype->pointed_type_ = type_;
ptype->is_defined_ = true;
ptype->cons_.push_back(new PtrConstructor(ptype));
ptype->rw_ = new PtrReaderWriter<T*>();
ptype->cmp_ = new TotalOrderComparator<T*>();
}
// const pointer type
if (!type_->pointed_type_ || !type_->is_const_)
{
Type *cptype = Reflection::getOrRegisterType(typeid(const T*), true);
cptype->name_ = type_->name_;
cptype->namespace_ = type_->namespace_;
cptype->is_const_ = true;
cptype->pointed_type_ = type_;
cptype->is_defined_ = true;
cptype->cons_.push_back(new ConstPtrConstructor(cptype));
cptype->rw_ = new PtrReaderWriter<const T*>();
cptype->cmp_ = new TotalOrderComparator<const T*>();
}
type_->is_defined_ = true;
}
template<typename T>
std::string Reflector<T>::purify(const std::string &s)
{
std::string r(s);
while (true)
{
std::string::size_type p = r.find(" COMMA ");
if (p == std::string::npos) break;
r.replace(p, 7, ", ");
};
return r;
}
template<typename T>
void Reflector<T>::split_qualified_name(const std::string &q, std::string &n, std::string &ns)
{
int templ = 0;
std::string::size_type split_point = std::string::npos;
std::string::size_type j = 0;
for (std::string::const_iterator i=q.begin(); i!=q.end(); ++i, ++j)
{
if (*i == '<') ++templ;
if (*i == '>') --templ;
if (templ == 0)
{
if (*i == ':' && (i+1)!=q.end() && *(i+1) == ':')
split_point = j;
}
}
if (split_point == std::string::npos)
{
ns.clear();
n = q;
}
else
{
n = q.substr(split_point+2);
ns = q.substr(0, split_point);
}
}
template<typename T>
void Reflector<T>::addBaseType(const Type &type)
{
type_->base_.push_back(&type);
}
template<typename T>
PropertyInfo *Reflector<T>::addProperty(PropertyInfo *pi)
{
type_->props_.push_back(pi);
return pi;
}
template<typename T>
MethodInfo *Reflector<T>::addMethod(MethodInfo *mi)
{
for (TempMethodList::iterator i=temp_methods_.begin(); i!=temp_methods_.end(); ++i)
{
if (mi->overrides(*i))
return *i;
}
temp_methods_.push_back(mi);
type_->methods_.push_back(mi);
return mi;
}
template<typename T>
void Reflector<T>::addEnumLabel(int v, const std::string &label, bool strip_namespace)
{
if (strip_namespace)
{
std::string::size_type p = label.rfind("::");
if (p != std::string::npos)
{
type_->labels_.insert(std::make_pair(v, label.substr(p+2)));
return;
}
}
type_->labels_.insert(std::make_pair(v, label));
}
template<typename T>
ConstructorInfo *Reflector<T>::addConstructor(ConstructorInfo *ci)
{
type_->cons_.push_back(ci);
return ci;
}
template<typename T>
std::string Reflector<T>::qualifyName(const std::string name) const
{
std::string s;
if (!type_->namespace_.empty())
{
s.append(type_->namespace_);
s.append("::");
}
if (!type_->name_.empty())
{
s.append(type_->name_);
s.append("::");
}
s.append(name);
return s;
}
template<typename T>
CustomAttributeProvider *Reflector<T>::addAttribute(const CustomAttribute *attrib)
{
return type_->addAttribute(attrib);
}
template<typename T>
void Reflector<T>::setReaderWriter(const ReaderWriter *rw)
{
type_->rw_ = rw;
}
template<typename T>
void Reflector<T>::setComparator(const Comparator *cmp)
{
type_->cmp_ = cmp;
}
}
#endif