Files
OpenSceneGraph/src/osgIntrospection/Type.cpp

294 lines
7.8 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
//osgIntrospection - Copyright (C) 2005 Marco Jez
#include <osgIntrospection/Type>
#include <osgIntrospection/Value>
#include <osgIntrospection/Reflection>
#include <osgIntrospection/PropertyInfo>
#include <osgIntrospection/MethodInfo>
#include <osgIntrospection/ReaderWriter>
#include <osgIntrospection/Utility>
#include <osgIntrospection/ConstructorInfo>
#include <osgIntrospection/Comparator>
#include <iterator>
#include <algorithm>
using namespace osgIntrospection;
namespace
{
template<typename T>
struct ObjectMatch
{
int list_pos;
float match;
const T *object;
bool operator < (const ObjectMatch &m) const
{
if (match > m.match) return true;
if (match < m.match) return false;
if (list_pos < m.list_pos) return true;
return false;
}
};
typedef ObjectMatch<MethodInfo> MethodMatch;
typedef ObjectMatch<ConstructorInfo> ConstructorMatch;
}
Type::~Type()
{
for (PropertyInfoList::const_iterator i=_props.begin(); i!=_props.end(); ++i)
delete *i;
for (MethodInfoList::const_iterator i=_methods.begin(); i!=_methods.end(); ++i)
delete *i;
for (ConstructorInfoList::const_iterator i=_cons.begin(); i!=_cons.end(); ++i)
delete *i;
delete _rw;
delete _cmp;
}
bool Type::isSubclassOf(const Type& type) const
{
check_defined();
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
if ((*i)->getExtendedTypeInfo() == type.getExtendedTypeInfo())
return true;
if ((*i)->isSubclassOf(type))
return true;
}
return false;
}
const MethodInfo *Type::getCompatibleMethod(const std::string& name, const ValueList& values, bool inherit) const
{
check_defined();
MethodInfoList allmethods;
const MethodInfoList *methods;
if (inherit)
{
getAllMethods(allmethods);
methods = &allmethods;
}
else
methods = &_methods;
typedef std::vector<MethodMatch> MatchList;
MatchList matches;
int pos = 0;
for (MethodInfoList::const_iterator j=methods->begin(); j!=methods->end(); ++j, ++pos)
{
const MethodInfo *mi = *j;
if (mi->getName().compare(name) == 0)
{
float match;
if (areArgumentsCompatible(values, mi->getParameters(), match))
{
MethodMatch mm;
mm.list_pos = pos;
mm.match = match;
mm.object = mi;
matches.push_back(mm);
}
}
}
if (!matches.empty())
{
std::sort(matches.begin(), matches.end());
return matches.front().object;
}
return 0;
}
const MethodInfo *Type::getMethod(const std::string& name, const ParameterInfoList& params, bool inherit) const
{
check_defined();
for (MethodInfoList::const_iterator j=_methods.begin(); j!=_methods.end(); ++j)
{
const MethodInfo *mi = *j;
if (mi->getName().compare(name) == 0)
{
if (areParametersCompatible(params, mi->getParameters()))
{
return mi;
}
}
}
if (inherit)
{
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
const MethodInfo *mi = (*i)->getMethod(name, params, true);
if (mi) return mi;
}
}
return 0;
}
void Type::getInheritedProviders(CustomAttributeProviderList& providers) const
{
check_defined();
providers.assign(_base.begin(), _base.end());
}
const PropertyInfo *Type::getProperty(const std::string& name, const Type& ptype, const ParameterInfoList& indices, bool inherit) const
{
check_defined();
for (PropertyInfoList::const_iterator i=_props.begin(); i!=_props.end(); ++i)
{
const PropertyInfo *pi = *i;
if (pi->getName() == name && pi->getPropertyType() == ptype)
{
if (areParametersCompatible(indices, pi->getIndexParameters()))
{
return pi;
}
}
}
if (inherit)
{
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
const PropertyInfo *pi = (*i)->getProperty(name, ptype, indices, true);
if (pi) return pi;
}
}
return 0;
}
Value Type::invokeMethod(const std::string& name, const Value& instance, ValueList& args, bool inherit) const
{
check_defined();
const MethodInfo *mi = getCompatibleMethod(name, args, inherit);
if (!mi) throw MethodNotFoundException(name, _name);
return mi->invoke(instance, args);
}
Value Type::invokeMethod(const std::string& name, Value& instance, ValueList& args, bool inherit) const
{
check_defined();
const MethodInfo *mi = getCompatibleMethod(name, args, inherit);
if (!mi) throw MethodNotFoundException(name, _name);
return mi->invoke(instance, args);
}
void Type::getAllProperties(PropertyInfoList& props) const
{
check_defined();
std::copy(_props.begin(), _props.end(), std::back_inserter(props));
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
(*i)->getAllProperties(props);
}
}
void Type::getPropertiesMap(PropertyInfoMap& props) const
{
check_defined();
props[this] = _props;
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
(*i)->getPropertiesMap(props);
}
}
void Type::getAllMethods(MethodInfoList& methods) const
{
check_defined();
std::copy(_methods.begin(), _methods.end(), std::back_inserter(methods));
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
(*i)->getAllMethods(methods);
}
}
void Type::getMethodsMap(MethodInfoMap& methods) const
{
check_defined();
methods[this] = _methods;
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
(*i)->getMethodsMap(methods);
}
}
Value Type::createInstance(ValueList& args) const
{
if (isAbstract())
throw TypeIsAbstractException(_ti);
const ConstructorInfo *ci = getCompatibleConstructor(args);
if (!ci)
throw ConstructorNotFoundException(_ti);
return ci->createInstance(args);
}
const ConstructorInfo *Type::getCompatibleConstructor(const ValueList& values) const
{
check_defined();
typedef std::vector<ConstructorMatch> MatchList;
MatchList matches;
int pos = 0;
for (ConstructorInfoList::const_iterator j=_cons.begin(); j!=_cons.end(); ++j, ++pos)
{
float match;
if (areArgumentsCompatible(values, (*j)->getParameters(), match))
{
ConstructorMatch mm;
mm.list_pos = pos;
mm.match = match;
mm.object = *j;
matches.push_back(mm);
}
}
if (!matches.empty())
{
std::sort(matches.begin(), matches.end());
return matches.front().object;
}
return 0;
}
const ConstructorInfo *Type::getConstructor(const ParameterInfoList& params) const
{
check_defined();
for (ConstructorInfoList::const_iterator j=_cons.begin(); j!=_cons.end(); ++j)
{
if (areParametersCompatible(params, (*j)->getParameters()))
return *j;
}
return 0;
}