JNIEXPORT jint JNICALL
Java_org_oic_simulator_server_SimulatorSingleResource_startResourceUpdation
(JNIEnv *env, jobject object, jobject type, jint interval, jobject listener)
{
    VALIDATE_CALLBACK_RET(env, listener, -1)

    SimulatorSingleResourceSP singleResource = simulatorSingleResourceToCpp(env, object);
    VALIDATE_OBJECT_RET(env, singleResource, -1)

    jobject listenerRef = env->NewGlobalRef(listener);
    updateCompleteCallback callback =  [listenerRef](const std::string & uri, const int id)
    {
        onAutoUpdationComplete(listenerRef, uri, id);
    };

    try
    {
        AutomationType automationType = AutomationTypeToCpp(env, type);
        int id = singleResource->startResourceUpdation(automationType, interval, callback);
        return id;
    }
    catch (InvalidArgsException &e)
    {
        throwInvalidArgsException(env, e.code(), e.what());
    }
    catch (SimulatorException &e)
    {
        throwSimulatorException(env, e.code(), e.what());
    }

    return -1;
}
JNIEXPORT jobject JNICALL
Java_org_oic_simulator_server_SimulatorCollectionResource_nativeGetSupportedResources
(JNIEnv *env, jobject object)
{
    auto collectionResource = simulatorCollectionResourceToCpp(env, object);
    VALIDATE_OBJECT_RET(env, collectionResource, nullptr)

    std::vector<std::string> supportedTypes = collectionResource->getSupportedResources();
    return JniVector(env).toJava(supportedTypes);
}
JNIEXPORT jint JNICALL
Java_org_oic_simulator_client_SimulatorRemoteResource_startVerification
(JNIEnv *env, jobject object, jint reqType, jobject listener)
{
    VALIDATE_CALLBACK_RET(env, listener, -1)

    SimulatorRemoteResourceSP resource = SimulatorRemoteResourceToCpp(env, object);
    VALIDATE_OBJECT_RET(env, resource, -1)

    // Convert RequestType
    RequestType type;
    switch (reqType)
    {
        case 0: type = RequestType::RQ_TYPE_GET; break;
        case 1: type = RequestType::RQ_TYPE_PUT; break;
        case 2: type = RequestType::RQ_TYPE_POST; break;
        case 3: type = RequestType::RQ_TYPE_DELETE; break;
        default: return -1;
    }

    try
    {
        SimulatorRemoteResource::StateCallback callback =  std::bind([](
                    const std::string & uid, int id, OperationState opState,
                    const std::shared_ptr<JniListenerHolder> &listenerRef)
        {
            onVerificationCallback(listenerRef->get(), uid, id, opState);
        }, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
        JniListenerHolder::create(env, listener));

        return resource->startVerification(type, callback);
    }
    catch (InvalidArgsException &e)
    {
        throwInvalidArgsException(env, e.code(), e.what());
    }
    catch (NoSupportException &e)
    {
        throwNoSupportException(env, e.what());
    }
    catch (OperationInProgressException &e)
    {
        throwOperationInProgressException(env, e.what());
    }
    catch (SimulatorException &e)
    {
        throwSimulatorException(env, e.code(), e.what());
    }

    return -1;
}
JNIEXPORT jobject JNICALL
Java_org_oic_simulator_server_SimulatorSingleResource_getAttribute
(JNIEnv *env, jobject object, jstring attrName)
{
    VALIDATE_INPUT_RET(env, !attrName, "Attribute name is null!", nullptr)

    SimulatorSingleResourceSP singleResource = simulatorSingleResourceToCpp(env, object);
    VALIDATE_OBJECT_RET(env, singleResource, nullptr)

    JniString jniAttrName(env, attrName);
    SimulatorResourceModel::Attribute attribute;
    if (singleResource->getAttribute(jniAttrName.get(), attribute))
        return simulatorResourceAttributeToJava(env, attribute);
    return nullptr;
}