void ReflectiveScriptClass::setProperty(
        QScriptValue& object, 
        const QScriptString & name, 
        uint id, 
        const QScriptValue& value)
{
    // std::cout << __FUNCTION__ << " " << 
    //     name.toString().toStdString() << std::endl;

    Node_ptr node = qscriptvalue_cast< Node_ptr >(object.data());

    if (node)
    {
        // Ensure it is initialized
        node->check_for_initialized();

        ::gsim::core::descriptor_type type = 
            node->descriptor->get_type();

        if (type == ::gsim::core::TYPE_STRUCT)
        {
            // because I am sure it is initialized
            if (id < node->children.size())
            {
                fromScriptValue(value, node->children[id]);
            }
        }
        else if (node->descriptor->is_repeated())
        {
            if (id < node->children.size())
            {
                fromScriptValue(value, node->children[id]);
            }
            else if (node->descriptor->is_variable_length() &&
                    QString(name) == "length")
            {
                // length property
                unsigned int length = value.toUInt32();

                node->descriptor->set_length(node->holder, length);

                // re-initialized in next access
                node->reset();
            }
        }
    }
}
QScriptValue ReflectiveScriptClass::property(
        const QScriptValue& object,
        const QScriptString& name, 
        uint id)
{
    // std::cout << __FUNCTION__ << std::endl;

    Node_ptr node = qscriptvalue_cast< Node_ptr >(object.data());

    if (node)
    {
        node->check_for_initialized();

        ::gsim::core::descriptor_type type = 
            node->descriptor->get_type();

        if (type == ::gsim::core::TYPE_STRUCT)
        {
            if (id < node->children.size())
            {
                return toScriptValue(node->children[id]);
            }
        }
        else if (node->descriptor->is_repeated())
        {
            if (id < node->children.size())
            {
                return toScriptValue(node->children[id]);
            }
            else if (QString(name) == "length")
            {
                // length property
                return QScriptValue((uint) node->children.size());
            }
        }
    }

    // Invalid value
    return QScriptValue();
}
QScriptClass::QueryFlags ReflectiveScriptClass::queryProperty(
        const QScriptValue& object, 
        const QScriptString& name, 
        QScriptClass::QueryFlags flags, 
        uint * id)
{
    // std::cout << __FUNCTION__ << " " << 
    //     name.toString().toStdString() << std::endl;

    // Invalid property identifier
    *id = std::numeric_limits< uint >::max();

    // Seen in Qt examples
    Node_ptr node = qscriptvalue_cast< Node_ptr >(object.data());

    if (node)
    {
        // Conversion from interned to normal string
        // for comparision
        const QString sName = name;

        node->check_for_initialized();

        ::gsim::core::descriptor_type type = 
            node->descriptor->get_type();

        if (type == ::gsim::core::TYPE_STRUCT)
        {
            unsigned int count = node->descriptor->get_children_count();

            // Search by name
            for (unsigned int i = 0; i < count; i++) 
            {
                // Maybe better with interned strings
                if (sName == node->descriptor->get_child_name(i))
                {
                    // Its identifier is its position
                    *id = i;

                    return QScriptClass::HandlesReadAccess |
                        QScriptClass::HandlesWriteAccess;
                }
            }
        }
        else if (node->descriptor->is_repeated())
        {
            unsigned int count = node->descriptor->get_length(node->holder);

            bool ok = false;
            *id = sName.toUInt(&ok);

            if (ok && *id < count)
            {
                return QScriptClass::HandlesReadAccess |
                    QScriptClass::HandlesWriteAccess;
            }
            else if (!ok && sName == "length")
            {
                *id = std::numeric_limits< uint >::max();

                if (node->descriptor->is_variable_length())
                    return QScriptClass::HandlesReadAccess |
                        QScriptClass::HandlesWriteAccess;

                return QScriptClass::HandlesReadAccess;
            }
        }
    }
    else
    {
        std::cerr << "Invalid node!" << std::endl;
    }

    return 0;
}
void ReflectiveScriptClass::fromScriptValue(
        const QScriptValue& value, Node_ptr node)
{
    // std::cout << __FUNCTION__ << std::endl;

    using namespace gsim::core;

    const descriptor_type type =
        node->descriptor->get_type();

    node->check_for_initialized();

    holder& hold = node->holder;
    descriptor_base const * descriptor = node->descriptor;

    switch(type)
    {

        case TYPE_STRUCT:
            {
                if (value.isObject())
                {
                    unsigned int count = 
                        node->descriptor->get_children_count();

                    // Search by name
                    for (unsigned int i = 0; i < count; i++) 
                    {
                        const char *childName = descriptor->get_child_name(i);
                        QScriptValue childValue = value.property(childName);

                        if (childValue.isValid())
                            fromScriptValue(childValue, node->children[i]);
                    }
                }
                else
                {
                    std::cerr << "Must be an object!" << std::endl;
                }
            }
            break;

        case TYPE_ARRAY:
            if (descriptor->get_slice()->get_type() == TYPE_CHAR)
            {
                const std::string str(value.toString().toStdString());
                descriptor->from_string(hold, str);
                break;
            }
        case TYPE_SEQUENCE:
            {
                unsigned int length = descriptor->get_length(hold);
                unsigned int newLength = value.property("length").toUInt32();

                if (descriptor->is_variable_length() &&
                        length != newLength)
                {
                    descriptor->set_length(hold, newLength);

                    node->reset();
                    node->check_for_initialized();
                }

                for (unsigned int i = 0; i < newLength && i < length; i++) 
                {
                    fromScriptValue(value.property(i),
                            node->children[i]);
                }
            }
            break;

        case TYPE_BOOL:
            hold.to_value< bool >() = value.toBool();
            break;
        case TYPE_OCTET:
            hold.to_value< unsigned char >() = value.toInteger();
            break;
        case TYPE_CHAR:
            hold.to_value< char >() = value.toInteger();
            break;
        case TYPE_SHORT:
            hold.to_value< short >() = value.toInteger();
            break;
        case TYPE_USHORT:
            hold.to_value< unsigned short >() = value.toUInt16();
            break;
        case TYPE_LONG:
            hold.to_value< int32_t >() = value.toInteger();
            break;
        case TYPE_ULONG:
            hold.to_value< uint32_t >() = value.toUInt32();
            break;
        case TYPE_LONGLONG:
            hold.to_value< int64_t >() = value.toInteger();
            break;
        case TYPE_ULONGLONG:
            hold.to_value< uint64_t >() = value.toInteger();
            break;

        case TYPE_STRING:
        case TYPE_WSTRING:
            {
                const std::string str(value.toString().toStdString());
                descriptor->from_string(hold, str);
            }
            break;

        case TYPE_ENUM:
            {
                const unsigned int count = descriptor->get_children_count();

                const QString str (value.toString());

                unsigned int idx = 
                    descriptor->get_child_index(
                            str.toStdString().c_str());

                if (idx < count)
                {
                    core::holder tmp(
                            descriptor->get_child_value(hold, idx));
                    descriptor->copy(tmp, hold);
                }

                // TODO debería devolverse excepción si se introdujo
                // un literal no válido.
            }
            break;

        case TYPE_DOUBLE:
            hold.to_value< double >() = value.toNumber();
            break;
        case TYPE_FLOAT:
            hold.to_value< float >() = value.toNumber();
        default:
            break;
    }

}