bool GridClientObjectWrapperConvertor::wrapSimpleType(const GridClientVariant& var, ObjectWrapper& objWrapper) {
    objWrapper.set_type(NONE);
    GridClientVariantVisitorImpl visitor(objWrapper);
    objWrapper.set_binary((void*) NULL, 0);
    var.accept(visitor);

    return objWrapper.type() != NONE;
}
template<class T> void unwrapCollection(const ObjectWrapper& objWrapper, std::vector<T>& res) {
    assert(objWrapper.type() == COLLECTION);
    assert(objWrapper.has_binary());

    res.clear();

    ::Collection coll;

    unmarshalMsg(objWrapper.binary().c_str(), objWrapper.binary().size(), coll);

    unwrapCollection(coll, res);
}
template<class K, class V> void unwrapMap(ObjectWrapper objWrapper, std::map<K, V>& res) {
    assert(objWrapper.type() == MAP);
    assert(objWrapper.has_binary());

    res.clear();

    ::Map map;

    unmarshalMsg((int8_t*) objWrapper.binary().c_str(), objWrapper.binary().size(), map);

    const ::google::protobuf::RepeatedPtrField< ::KeyValue >& repFileds = map.entry();

    std::for_each(repFileds.begin(), repFileds.end(), MapInserter<K, V, ::KeyValue>(res));
}
static bool doUnwrapSimpleType(const ObjectWrapper& objWrapper, GridClientVariant& var) {
    assert(objWrapper.has_binary());

    GG_LOG_DEBUG("Unwrap simple type: %s", objWrapper.DebugString().c_str());

    string binary = objWrapper.binary();

    bool unwrapRes = false;

    switch (objWrapper.type()) {
        case NONE:
            return true;
        case BOOL:
            return getBoolValue(binary, var);

        case BYTE:
            return getByteValue(binary, var);

        case BYTES:
            return getBytesValue(binary, var);

        case INT32:
            return getInt32Value(binary, var);

        case INT64:
            return getInt64Value(binary, var);

        case SHORT:
            return getInt16Value(binary, var);

        case STRING:
            var.set(binary);
            return true;

        case DOUBLE:
            return getDoubleValue(binary, var);

        case FLOAT:
            return getFloatValue(binary, var);

        case TASK_BEAN:
            return getTaskTesult(binary, var);

        default: // Non-simple type

            break;
    }

    return unwrapRes;
}
static void unwrap(const ObjectWrapper& objWrapper, GridClientNode& res) {
    assert(objWrapper.type() == NODE_BEAN);
    assert(objWrapper.has_binary());

    ::ProtoNodeBean bean;

    boost::asio::io_service ioSrvc;
    boost::asio::ip::tcp::resolver resolver(ioSrvc);

    unmarshalMsg((int8_t*) objWrapper.binary().c_str(), objWrapper.binary().size(), bean);

    GridNodeMarshallerHelper helper(res);

    helper.setNodeId(GridUuid::fromBytes(bean.nodeid()));

    GridClientVariant consistentId;

    GridClientObjectWrapperConvertor::unwrapSimpleType(bean.consistentid(), consistentId);

    helper.setConsistentId(consistentId);

    int tcpport = bean.tcpport();
    int jettyport = bean.jettyport();

    std::vector<GridSocketAddress> addresses;

    for (int i = 0; i < bean.jettyaddress_size(); ++i) {
        if (bean.jettyaddress(i).size()) {
            GridSocketAddress newJettyAddress = GridSocketAddress(bean.jettyaddress(i), jettyport);

            boost::asio::ip::tcp::resolver::query queryIp(bean.jettyaddress(i),
                boost::lexical_cast<std::string>(bean.jettyport()));

            boost::system::error_code ec;

            boost::asio::ip::tcp::resolver::iterator endpoint_iter = resolver.resolve(queryIp, ec);

            if (!ec)
                addresses.push_back(newJettyAddress);
            else
                GG_LOG_ERROR("Error resolving hostname: %s, %s", bean.jettyaddress(i).c_str(), ec.message().c_str());
        }
    }

    for (int i = 0; i < bean.jettyhostname_size(); ++i) {
        if (bean.jettyhostname(i).size()) {
            GridSocketAddress newJettyAddress = GridSocketAddress(bean.jettyhostname(i), jettyport);

            boost::asio::ip::tcp::resolver::query queryHostname(bean.jettyhostname(i),
                boost::lexical_cast<std::string>(bean.jettyport()));

            boost::system::error_code ec;

            boost::asio::ip::tcp::resolver::iterator endpoint_iter = resolver.resolve(queryHostname, ec);

            if (!ec)
                addresses.push_back(newJettyAddress);
            else
                GG_LOG_ERROR("Error resolving hostname: %s, %s", bean.jettyhostname(i).c_str(), ec.message().c_str());
        }

    }

    helper.setJettyAddresses(addresses);
    addresses.clear();

    for (int i = 0; i < bean.tcpaddress_size(); ++i) {
        if (bean.tcpaddress(i).size()) {
            GridSocketAddress newTCPAddress = GridSocketAddress(bean.tcpaddress(i), tcpport);

            boost::asio::ip::tcp::resolver::query queryIp(bean.tcpaddress(i),
                boost::lexical_cast<std::string>(bean.tcpport()));

            boost::system::error_code ec;

            boost::asio::ip::tcp::resolver::iterator endpoint_iter = resolver.resolve(queryIp, ec);

            if (!ec)
                addresses.push_back(newTCPAddress);
            else
                GG_LOG_ERROR("Error resolving hostname: %s, %s", bean.tcpaddress(i).c_str(), ec.message().c_str());
        }
    }

    for (int i = 0; i < bean.tcphostname_size(); ++i) {
        if (bean.tcphostname(i).size()) {
            GridSocketAddress newTCPAddress = GridSocketAddress(bean.tcphostname(i), tcpport);

            boost::asio::ip::tcp::resolver::query queryHostname(bean.tcphostname(i),
                boost::lexical_cast<std::string>(bean.tcpport()));

            boost::system::error_code ec;

            boost::asio::ip::tcp::resolver::iterator endpoint_iter = resolver.resolve(queryHostname, ec);

            if (!ec)
                addresses.push_back(newTCPAddress);
            else
                GG_LOG_ERROR("Error resolving hostname: %s, %s", bean.tcphostname(i).c_str(), ec.message().c_str());
        }
    }

    helper.setTcpAddresses(addresses);

    std::map<GridClientVariant, GridClientVariant> cachesVars;
    unwrapMap(bean.caches(), cachesVars);
    helper.setCaches(cachesVars);

    std::map<GridClientVariant, GridClientVariant> attrs;
    unwrapMap(bean.attributes(), attrs);
    helper.setAttributes(attrs);

    if (bean.has_metrics()) {
        const ::ProtoNodeMetricsBean& metrics = bean.metrics();
        GridClientNodeMetricsBean metricsBean;

        metricsBean.setStartTime(metrics.starttime());
        metricsBean.setAverageActiveJobs(metrics.averageactivejobs());
        metricsBean.setAverageCancelledJobs(metrics.averagecancelledjobs());
        metricsBean.setAverageCpuLoad(metrics.averagecpuload());
        metricsBean.setAverageJobExecuteTime(metrics.averagejobexecutetime());
        metricsBean.setAverageJobWaitTime(metrics.averagejobwaittime());
        metricsBean.setAverageRejectedJobs(metrics.averagerejectedjobs());
        metricsBean.setAverageWaitingJobs(metrics.averagewaitingjobs());
        metricsBean.setCurrentActiveJobs(metrics.currentactivejobs());
        metricsBean.setCurrentCancelledJobs(metrics.currentcancelledjobs());
        metricsBean.setCurrentCpuLoad(metrics.currentcpuload());
        metricsBean.setCurrentDaemonThreadCount(metrics.currentdaemonthreadcount());
        metricsBean.setCurrentIdleTime(metrics.currentidletime());
        metricsBean.setCurrentJobExecuteTime(metrics.currentjobexecutetime());
        metricsBean.setCurrentJobWaitTime(metrics.currentjobwaittime());
        metricsBean.setCurrentRejectedJobs(metrics.currentrejectedjobs());
        metricsBean.setCurrentThreadCount(metrics.currentthreadcount());
        metricsBean.setCurrentWaitingJobs(metrics.currentwaitingjobs());
        metricsBean.setFileSystemFreeSpace(metrics.filesystemfreespace());
        metricsBean.setFileSystemTotalSpace(metrics.filesystemtotalspace());
        metricsBean.setFileSystemUsableSpace(metrics.filesystemusablespace());
        metricsBean.setHeapMemoryCommitted(metrics.heapmemorycommitted());
        metricsBean.setHeapMemoryInitialized(metrics.heapmemoryinitialized());
        metricsBean.setHeapMemoryMaximum(metrics.heapmemorymaximum());
        metricsBean.setHeapMemoryUsed(metrics.heapmemoryused());
        metricsBean.setLastDataVersion(metrics.lastdataversion());
        metricsBean.setLastUpdateTime(metrics.lastupdatetime());
        metricsBean.setMaximumActiveJobs(metrics.maximumactivejobs());
        metricsBean.setMaximumCancelledJobs(metrics.maximumcancelledjobs());
        metricsBean.setMaximumJobExecuteTime(metrics.maximumjobexecutetime());
        metricsBean.setMaximumJobWaitTime(metrics.maximumjobwaittime());
        metricsBean.setMaximumRejectedJobs(metrics.maximumrejectedjobs());
        metricsBean.setMaximumThreadCount(metrics.maximumthreadcount());
        metricsBean.setMaximumWaitingJobs(metrics.maximumwaitingjobs());
        metricsBean.setNodeStartTime(metrics.nodestarttime());
        metricsBean.setNonHeapMemoryCommitted(metrics.nonheapmemorycommitted());
        metricsBean.setNonHeapMemoryInitialized(metrics.nonheapmemoryinitialized());
        metricsBean.setNonHeapMemoryMaximum(metrics.nonheapmemorymaximum());
        metricsBean.setNonHeapMemoryUsed(metrics.nonheapmemoryused());
        metricsBean.setTotalCancelledJobs(metrics.totalcancelledjobs());
        metricsBean.setTotalCpus(metrics.totalcpus());
        metricsBean.setTotalExecutedJobs(metrics.totalexecutedjobs());
        metricsBean.setTotalIdleTime(metrics.totalidletime());
        metricsBean.setTotalRejectedJobs(metrics.totalrejectedjobs());
        metricsBean.setTotalStartedThreadCount(metrics.totalstartedthreadcount());
        metricsBean.setUpTime(metrics.uptime());

        helper.setMetrics(metricsBean);
    }
}
static void unwrapResponse(const ObjectWrapper& objWrapper, ProtoResponse& resp) {
    assert(objWrapper.type() == RESPONSE);
    assert(objWrapper.has_binary());

    unmarshalMsg((int8_t*) objWrapper.binary().c_str(), objWrapper.binary().size(), resp);
}