/* -*-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

#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 <osgIntrospection/ConverterProxy>
#include <osgIntrospection/Converter>
#include <osgIntrospection/Utility>

#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*, const T*, T&, and const T&. You
    /// should NEVER create reflectors for pointer or reference types
    /// explicitly.
    ///
    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 a protected method description to the current type.
        MethodInfo* addProtectedMethod(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);

        /// Adds a protected constructor description to the current
        /// type.
        ConstructorInfo* addProtectedConstructor(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);

        /// Sets the current type's declaring file.
        void setDeclaringFile(const std::string& file) const;

    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();
        void init_reference_types();
        void init_void_converter();
        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;
        TempMethodList _temp_protected_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;
        typedef ProtectedConstructorInstanceCreator<typename Reflector<T>::reflected_type> invalid_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;
        typedef ProtectedConstructorInstanceCreator<typename Reflector<T>::reflected_type> invalid_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;
        typedef ProtectedConstructorInstanceCreator<typename Reflector<T>::reflected_type> invalid_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()));
        }
    };

    template<typename T>
    struct WAtomicValueReflector: ValueReflector<T>
    {
        typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;

        WAtomicValueReflector(const std::string& name, const std::string& ns)
        :    ValueReflector<T>(name, ns)
        {
            setReaderWriter(new StdWReaderWriter<T>);
            setComparator(new PartialOrderComparator<T>);
            addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
        }

        WAtomicValueReflector(const std::string& qname)
        :    ValueReflector<T>(qname)
        {
            setReaderWriter(new StdWReaderWriter<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
            {
                return getInstance<T>(instance).at(i);
            }

            virtual Value get(const Value& instance, int i) const
            {
                return getInstance<T>(instance).at(i);
            }
        };

        struct Setter: PropertySetter
        {
            virtual void set(Value& instance, int i, const Value& v) const
            {
                getInstance<T>(instance).at(i) = variant_cast<const typename T::value_type& >(v);
            }
        };

        struct Counter: PropertyCounter
        {
            virtual int count(const Value& instance) const
            {
                return static_cast<int>(getInstance<T>(instance).size());
            }
        };

        struct Adder: PropertyAdder
        {
            virtual void add(Value& instance, const Value& v) const
            {
                getInstance<T>(instance).push_back(variant_cast<const typename T::value_type& >(v));
            }
        };

        struct Remover: PropertyRemover
        {
            virtual void remove(Value& instance, int i) const
            {
                T& ctr = getInstance<T>(instance);
                typename T::iterator j=ctr.begin();
                std::advance(j, i);
                ctr.erase(j);
            }
        };

        struct Inserter: PropertyInserter
        {
            virtual void insert(Value& instance, int i, const Value& v) const
            {
                T& ctr = getInstance<T>(instance);
                typename T::iterator j=ctr.begin();
                std::advance(j, i);
                ctr.insert(j, variant_cast<const typename T::value_type& >(v));
            }
        };

        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), "Item", 0, 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));
            pi->addAttribute(new CustomPropertyInsertAttribute(new Inserter));

            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 = getInstance<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 = getInstance<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
            {
                return static_cast<int>(getInstance<T>(instance).size());
            }
        };

        struct Adder: PropertyAdder
        {
            virtual void add(Value& instance, const Value& v) const
            {
                getInstance<T>(instance).insert(variant_cast<const typename T::value_type& >(v));
            }
        };

        struct Remover: PropertyRemover
        {
            virtual void remove(Value& instance, int i) const
            {
                T& ctr = getInstance<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), "Item", 0, 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 = getInstance<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 = getInstance<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 = getInstance<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
            {
                return static_cast<int>(getInstance<T>(instance).size());
            }
        };

        struct Adder: PropertyAdder
        {
            virtual void add(Value& instance, const Value& v) const
            {
                getInstance<T>(instance).push_back(variant_cast<const typename T::value_type& >(v));
            }
        };

        struct Remover: PropertyRemover
        {
            virtual void remove(Value& instance, int i) const
            {
                T& ctr = getInstance<T>(instance);
                typename T::iterator j=ctr.begin();
                std::advance(j, i);
                ctr.erase(j);
            }
        };

        struct Inserter: PropertyInserter
        {
            virtual void insert(Value& instance, int i, const Value& v) const
            {
                T& ctr = getInstance<T>(instance);
                typename T::iterator j=ctr.begin();
                std::advance(j, i);
                ctr.insert(j, variant_cast<const typename T::value_type& >(v));
            }
        };

        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), "Item", 0, 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));
            pi->addAttribute(new CustomPropertyInsertAttribute(new Inserter));

            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 = getInstance<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 = getInstance<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
            {
                getInstance<T>(instance).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 = getInstance<T>(instance);
                for (const_iterator i=ctr.begin(); 
                    i!=ctr.end(); 
                    ++i)
                {
                    values.push_back(Value(i->first).convertTo(_itype));
                }
            }
        };

        struct Remover: PropertyRemover
        {
            virtual void remove(Value& instance, ValueList& values) const
            {
                getInstance<T>(instance).erase(getInstance<key_type>(values.front()));
            }
        };

        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), "Item", 0, 0, 0);
            pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
            pi->addAttribute(new CustomPropertySetAttribute(new Setter));
            pi->addAttribute(new CustomIndexAttribute(new Indexer));
            pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover));

            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 getInstance<T>(instance).first;
                case 1: return getInstance<T>(instance).second;
                default: return Value();
                }
            }

            virtual Value get(Value& instance) const
            {
                switch (_i)
                {
                case 0: return getInstance<T>(instance).first;
                case 1: return getInstance<T>(instance).second;
                default: return Value();
                }
            }

            virtual void set(Value& instance, const Value& v) const
            {
                T& ctr = getInstance<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(extended_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(extended_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(extended_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(extended_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*>();
        }

        init_reference_types();
        init_void_converter();

        _type->_is_defined = true;
    }

    template<typename T>
    void Reflector<T>::init_reference_types()
    {
        // reference type
        if (!_type->_referenced_type)
        {
            Type* ptype = Reflection::getOrRegisterType(extended_typeid<T&>(), true);
            ptype->_name = _type->_name;
            ptype->_namespace = _type->_namespace;
            ptype->_referenced_type = _type;
            ptype->_is_defined = true;
        }

        // const reference type
        if (!_type->_referenced_type || !_type->_is_const)
        {
            Type* cptype = Reflection::getOrRegisterType(extended_typeid<const T&>(), true);
            cptype->_name = _type->_name;
            cptype->_namespace = _type->_namespace;
            cptype->_is_const = true;
            cptype->_referenced_type = _type;
            cptype->_is_defined = true;
        }
    }

    template<>
    void Reflector<void>::init_reference_types();


    template<typename T>
    void Reflector<T>::init_void_converter()
    {
        const osgIntrospection::Type& st = typeof(T*);
        const osgIntrospection::Type& cst = typeof(const T*);
        const osgIntrospection::Type& dt = typeof(void*);
        const osgIntrospection::Type& cdt = typeof(const void*);
        osgIntrospection::ConverterProxy cp1(st, dt, new osgIntrospection::ReinterpretConverter<T* , void*>);
        osgIntrospection::ConverterProxy cp2(cst, cdt, new osgIntrospection::ReinterpretConverter<const T* , const void*>);
        osgIntrospection::ConverterProxy cp1c(st, cdt, new osgIntrospection::ReinterpretConverter<T* , const void*>);
        osgIntrospection::ConverterProxy cp3(dt, st, new osgIntrospection::ReinterpretConverter<void*, T* >);
        osgIntrospection::ConverterProxy cp4(cdt, cst, new osgIntrospection::ReinterpretConverter<const void*, const T* >);
        osgIntrospection::ConverterProxy cp3c(dt, cst, new osgIntrospection::ReinterpretConverter<void*, const T* >);
    }

    template<>
    void Reflector<void>::init_void_converter();

    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>
    MethodInfo* Reflector<T>::addProtectedMethod(MethodInfo* mi)
    {
        for (TempMethodList::iterator i=_temp_protected_methods.begin(); i!=_temp_protected_methods.end(); ++i)
        {
            if (mi->overrides(*i))
                return *i;
        }

        _temp_protected_methods.push_back(mi);
        _type->_protected_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>
    ConstructorInfo* Reflector<T>::addProtectedConstructor(ConstructorInfo* ci)
    {
        _type->_protected_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;
    }

    template<typename T>
    void Reflector<T>::setDeclaringFile(const std::string& file) const
    {
        _type->_declaringFile = file;
    }

}

#endif

