/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 *
 * Code generated by Microsoft (R) AutoRest Code Generator.
 */

package com.microsoft.azure.batch.protocol.implementation;

import retrofit2.Retrofit;
import com.microsoft.azure.batch.protocol.ComputeNodes;
import com.google.common.base.Joiner;
import com.google.common.reflect.TypeToken;
import com.microsoft.azure.AzureServiceFuture;
import com.microsoft.azure.batch.protocol.models.BatchErrorException;
import com.microsoft.azure.batch.protocol.models.ComputeNode;
import com.microsoft.azure.batch.protocol.models.ComputeNodeAddUserHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeAddUserOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeDeleteUserHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeDeleteUserOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeDisableSchedulingHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeDisableSchedulingOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeEnableSchedulingHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeEnableSchedulingOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeGetHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeGetOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeGetRemoteDesktopHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeGetRemoteDesktopOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeGetRemoteLoginSettingsHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeGetRemoteLoginSettingsOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeGetRemoteLoginSettingsResult;
import com.microsoft.azure.batch.protocol.models.ComputeNodeListHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeListNextOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeListOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeRebootHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeRebootOption;
import com.microsoft.azure.batch.protocol.models.ComputeNodeRebootOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeReimageHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeReimageOption;
import com.microsoft.azure.batch.protocol.models.ComputeNodeReimageOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeUpdateUserHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeUpdateUserOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeUploadBatchServiceLogsHeaders;
import com.microsoft.azure.batch.protocol.models.ComputeNodeUploadBatchServiceLogsOptions;
import com.microsoft.azure.batch.protocol.models.ComputeNodeUser;
import com.microsoft.azure.batch.protocol.models.DisableComputeNodeSchedulingOption;
import com.microsoft.azure.batch.protocol.models.NodeDisableSchedulingParameter;
import com.microsoft.azure.batch.protocol.models.NodeRebootParameter;
import com.microsoft.azure.batch.protocol.models.NodeReimageParameter;
import com.microsoft.azure.batch.protocol.models.NodeUpdateUserParameter;
import com.microsoft.azure.batch.protocol.models.PageImpl;
import com.microsoft.azure.batch.protocol.models.UploadBatchServiceLogsConfiguration;
import com.microsoft.azure.batch.protocol.models.UploadBatchServiceLogsResult;
import com.microsoft.azure.ListOperationCallback;
import com.microsoft.azure.Page;
import com.microsoft.azure.PagedList;
import com.microsoft.rest.DateTimeRfc1123;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceFuture;
import com.microsoft.rest.ServiceResponseWithHeaders;
import com.microsoft.rest.Validator;
import java.io.InputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import okhttp3.ResponseBody;
import org.joda.time.DateTime;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.HTTP;
import retrofit2.http.Path;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Query;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
import retrofit2.Response;
import rx.functions.Func1;
import rx.Observable;

// Custom Imports
import java.io.OutputStream;
import rx.exceptions.Exceptions;
import rx.functions.Action1;

/**
 * An instance of this class provides access to all the operations defined
 * in ComputeNodes.
 */
public class ComputeNodesImpl implements ComputeNodes {
    /** The Retrofit service to perform REST calls. */
    private ComputeNodesService service;
    /** The service client containing this operation class. */
    private BatchServiceClientImpl client;

    /**
     * Initializes an instance of ComputeNodesImpl.
     *
     * @param retrofit the Retrofit instance built from a Retrofit Builder.
     * @param client the instance of the service client containing this operation class.
     */
    public ComputeNodesImpl(Retrofit retrofit, BatchServiceClientImpl client) {
        this.service = retrofit.create(ComputeNodesService.class);
        this.client = client;
    }

    /**
     * The interface defining all the services for ComputeNodes to be
     * used by Retrofit to perform actually REST calls.
     */
    interface ComputeNodesService {
        @Headers({ "Content-Type: application/json; odata=minimalmetadata; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes addUser" })
        @POST("pools/{poolId}/nodes/{nodeId}/users")
        Observable<Response<ResponseBody>> addUser(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Body ComputeNodeUser user, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes deleteUser" })
        @HTTP(path = "pools/{poolId}/nodes/{nodeId}/users/{userName}", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> deleteUser(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Path("userName") String userName, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; odata=minimalmetadata; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes updateUser" })
        @PUT("pools/{poolId}/nodes/{nodeId}/users/{userName}")
        Observable<Response<ResponseBody>> updateUser(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Path("userName") String userName, @Body NodeUpdateUserParameter nodeUpdateUserParameter, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes get" })
        @GET("pools/{poolId}/nodes/{nodeId}")
        Observable<Response<ResponseBody>> get(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("$select") String select, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; odata=minimalmetadata; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes reboot" })
        @POST("pools/{poolId}/nodes/{nodeId}/reboot")
        Observable<Response<ResponseBody>> reboot(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Body NodeRebootParameter nodeRebootParameter, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; odata=minimalmetadata; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes reimage" })
        @POST("pools/{poolId}/nodes/{nodeId}/reimage")
        Observable<Response<ResponseBody>> reimage(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Body NodeReimageParameter nodeReimageParameter, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; odata=minimalmetadata; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes disableScheduling" })
        @POST("pools/{poolId}/nodes/{nodeId}/disablescheduling")
        Observable<Response<ResponseBody>> disableScheduling(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Body NodeDisableSchedulingParameter nodeDisableSchedulingParameter, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes enableScheduling" })
        @POST("pools/{poolId}/nodes/{nodeId}/enablescheduling")
        Observable<Response<ResponseBody>> enableScheduling(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes getRemoteLoginSettings" })
        @GET("pools/{poolId}/nodes/{nodeId}/remoteloginsettings")
        Observable<Response<ResponseBody>> getRemoteLoginSettings(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes getRemoteDesktop" })
        @GET("pools/{poolId}/nodes/{nodeId}/rdp")
        @Streaming
        Observable<Response<ResponseBody>> getRemoteDesktop(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; odata=minimalmetadata; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes uploadBatchServiceLogs" })
        @POST("pools/{poolId}/nodes/{nodeId}/uploadbatchservicelogs")
        Observable<Response<ResponseBody>> uploadBatchServiceLogs(@Path("poolId") String poolId, @Path("nodeId") String nodeId, @Body UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes list" })
        @GET("pools/{poolId}/nodes")
        Observable<Response<ResponseBody>> list(@Path("poolId") String poolId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("$filter") String filter, @Query("$select") String select, @Query("maxresults") Integer maxResults, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.ComputeNodes listNext" })
        @GET
        Observable<Response<ResponseBody>> listNext(@Url String nextUrl, @Header("accept-language") String acceptLanguage, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("User-Agent") String userAgent);

    }

    //CUSTOM METHOD
    /**
     * Gets the Remote Desktop Protocol file for the specified compute node.
     * Before you can access a node by using the RDP file, you must create a user account on the node. This API can only be invoked on pools created with a cloud service configuration. For pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the pool that contains the compute node.
     * @param nodeId The ID of the compute node for which you want to get the Remote Desktop Protocol file.
     * @param outputStream The OutputStream object which data will be written to if successful.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void getRemoteDesktop(String poolId, String nodeId, final OutputStream outputStream) {
        getRemoteDesktopAsync(poolId, nodeId).doOnNext(
            new Action1<InputStream>() {
                @Override
                public void call(InputStream input) {
                    byte[] data = new byte[4096];
                    int nRead;
                    try {
                        while ((nRead = input.read(data, 0, data.length)) != -1) {
                            outputStream.write(data, 0, nRead);
                        }
                        outputStream.flush();
                    } catch (IOException e) {
                        throw Exceptions.propagate(e);
                    }
                }
            }).toBlocking().single();
    }

    // CUSTOM METHOD
    /**
     * Gets the Remote Desktop Protocol file for the specified compute node.
     * Before you can access a node by using the RDP file, you must create a user account on the node. This API can only be invoked on pools created with a cloud service configuration. For pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the pool that contains the compute node.
     * @param nodeId The ID of the compute node for which you want to get the Remote Desktop Protocol file.
     * @param computeNodeGetRemoteDesktopOptions Additional parameters for the operation
     * @param outputStream The OutputStream object which data will be written to if successful.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void getRemoteDesktop(String poolId, String nodeId, ComputeNodeGetRemoteDesktopOptions computeNodeGetRemoteDesktopOptions, final OutputStream outputStream) {
        getRemoteDesktopAsync(poolId, nodeId, computeNodeGetRemoteDesktopOptions).doOnNext(
            new Action1<InputStream>() {
                @Override
                public void call(InputStream input) {
                    byte[] data = new byte[4096];
                    int nRead;
                    try {
                        while ((nRead = input.read(data, 0, data.length)) != -1) {
                            outputStream.write(data, 0, nRead);
                        }
                        outputStream.flush();
                    } catch (IOException e) {
                        throw Exceptions.propagate(e);
                    }
                }
            }).toBlocking().single();
    }


    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void addUser(String poolId, String nodeId, ComputeNodeUser user) {
        addUserWithServiceResponseAsync(poolId, nodeId, user).toBlocking().single().body();
    }

    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> addUserAsync(String poolId, String nodeId, ComputeNodeUser user, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(addUserWithServiceResponseAsync(poolId, nodeId, user), serviceCallback);
    }

    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> addUserAsync(String poolId, String nodeId, ComputeNodeUser user) {
        return addUserWithServiceResponseAsync(poolId, nodeId, user).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>> addUserWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeUser user) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (user == null) {
            throw new IllegalArgumentException("Parameter user is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(user);
        final ComputeNodeAddUserOptions computeNodeAddUserOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.addUser(poolId, nodeId, user, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders> clientResponse = addUserDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @param computeNodeAddUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void addUser(String poolId, String nodeId, ComputeNodeUser user, ComputeNodeAddUserOptions computeNodeAddUserOptions) {
        addUserWithServiceResponseAsync(poolId, nodeId, user, computeNodeAddUserOptions).toBlocking().single().body();
    }

    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @param computeNodeAddUserOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> addUserAsync(String poolId, String nodeId, ComputeNodeUser user, ComputeNodeAddUserOptions computeNodeAddUserOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(addUserWithServiceResponseAsync(poolId, nodeId, user, computeNodeAddUserOptions), serviceCallback);
    }

    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @param computeNodeAddUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> addUserAsync(String poolId, String nodeId, ComputeNodeUser user, ComputeNodeAddUserOptions computeNodeAddUserOptions) {
        return addUserWithServiceResponseAsync(poolId, nodeId, user, computeNodeAddUserOptions).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Adds a user Account to the specified Compute Node.
     * You can add a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to create a user Account.
     * @param user The user Account to be created.
     * @param computeNodeAddUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>> addUserWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeUser user, ComputeNodeAddUserOptions computeNodeAddUserOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (user == null) {
            throw new IllegalArgumentException("Parameter user is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(user);
        Validator.validate(computeNodeAddUserOptions);
        Integer timeout = null;
        if (computeNodeAddUserOptions != null) {
            timeout = computeNodeAddUserOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeAddUserOptions != null) {
            clientRequestId = computeNodeAddUserOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeAddUserOptions != null) {
            returnClientRequestId = computeNodeAddUserOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeAddUserOptions != null) {
            ocpDate = computeNodeAddUserOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.addUser(poolId, nodeId, user, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders> clientResponse = addUserDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, ComputeNodeAddUserHeaders> addUserDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Void, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(201, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeAddUserHeaders.class);
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void deleteUser(String poolId, String nodeId, String userName) {
        deleteUserWithServiceResponseAsync(poolId, nodeId, userName).toBlocking().single().body();
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> deleteUserAsync(String poolId, String nodeId, String userName, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(deleteUserWithServiceResponseAsync(poolId, nodeId, userName), serviceCallback);
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> deleteUserAsync(String poolId, String nodeId, String userName) {
        return deleteUserWithServiceResponseAsync(poolId, nodeId, userName).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>> deleteUserWithServiceResponseAsync(String poolId, String nodeId, String userName) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (userName == null) {
            throw new IllegalArgumentException("Parameter userName is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeDeleteUserOptions computeNodeDeleteUserOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.deleteUser(poolId, nodeId, userName, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders> clientResponse = deleteUserDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @param computeNodeDeleteUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void deleteUser(String poolId, String nodeId, String userName, ComputeNodeDeleteUserOptions computeNodeDeleteUserOptions) {
        deleteUserWithServiceResponseAsync(poolId, nodeId, userName, computeNodeDeleteUserOptions).toBlocking().single().body();
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @param computeNodeDeleteUserOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> deleteUserAsync(String poolId, String nodeId, String userName, ComputeNodeDeleteUserOptions computeNodeDeleteUserOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(deleteUserWithServiceResponseAsync(poolId, nodeId, userName, computeNodeDeleteUserOptions), serviceCallback);
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @param computeNodeDeleteUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> deleteUserAsync(String poolId, String nodeId, String userName, ComputeNodeDeleteUserOptions computeNodeDeleteUserOptions) {
        return deleteUserWithServiceResponseAsync(poolId, nodeId, userName, computeNodeDeleteUserOptions).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes a user Account from the specified Compute Node.
     * You can delete a user Account to a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to delete a user Account.
     * @param userName The name of the user Account to delete.
     * @param computeNodeDeleteUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>> deleteUserWithServiceResponseAsync(String poolId, String nodeId, String userName, ComputeNodeDeleteUserOptions computeNodeDeleteUserOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (userName == null) {
            throw new IllegalArgumentException("Parameter userName is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeDeleteUserOptions);
        Integer timeout = null;
        if (computeNodeDeleteUserOptions != null) {
            timeout = computeNodeDeleteUserOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeDeleteUserOptions != null) {
            clientRequestId = computeNodeDeleteUserOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeDeleteUserOptions != null) {
            returnClientRequestId = computeNodeDeleteUserOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeDeleteUserOptions != null) {
            ocpDate = computeNodeDeleteUserOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.deleteUser(poolId, nodeId, userName, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders> clientResponse = deleteUserDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, ComputeNodeDeleteUserHeaders> deleteUserDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Void, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeDeleteUserHeaders.class);
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void updateUser(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter) {
        updateUserWithServiceResponseAsync(poolId, nodeId, userName, nodeUpdateUserParameter).toBlocking().single().body();
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> updateUserAsync(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(updateUserWithServiceResponseAsync(poolId, nodeId, userName, nodeUpdateUserParameter), serviceCallback);
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> updateUserAsync(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter) {
        return updateUserWithServiceResponseAsync(poolId, nodeId, userName, nodeUpdateUserParameter).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>> updateUserWithServiceResponseAsync(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (userName == null) {
            throw new IllegalArgumentException("Parameter userName is required and cannot be null.");
        }
        if (nodeUpdateUserParameter == null) {
            throw new IllegalArgumentException("Parameter nodeUpdateUserParameter is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(nodeUpdateUserParameter);
        final ComputeNodeUpdateUserOptions computeNodeUpdateUserOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.updateUser(poolId, nodeId, userName, nodeUpdateUserParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders> clientResponse = updateUserDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @param computeNodeUpdateUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void updateUser(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter, ComputeNodeUpdateUserOptions computeNodeUpdateUserOptions) {
        updateUserWithServiceResponseAsync(poolId, nodeId, userName, nodeUpdateUserParameter, computeNodeUpdateUserOptions).toBlocking().single().body();
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @param computeNodeUpdateUserOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> updateUserAsync(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter, ComputeNodeUpdateUserOptions computeNodeUpdateUserOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(updateUserWithServiceResponseAsync(poolId, nodeId, userName, nodeUpdateUserParameter, computeNodeUpdateUserOptions), serviceCallback);
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @param computeNodeUpdateUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> updateUserAsync(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter, ComputeNodeUpdateUserOptions computeNodeUpdateUserOptions) {
        return updateUserWithServiceResponseAsync(poolId, nodeId, userName, nodeUpdateUserParameter, computeNodeUpdateUserOptions).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates the password and expiration time of a user Account on the specified Compute Node.
     * This operation replaces of all the updatable properties of the Account. For example, if the expiryTime element is not specified, the current value is replaced with the default value, not left unmodified. You can update a user Account on a Compute Node only when it is in the idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the machine on which you want to update a user Account.
     * @param userName The name of the user Account to update.
     * @param nodeUpdateUserParameter The parameters for the request.
     * @param computeNodeUpdateUserOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>> updateUserWithServiceResponseAsync(String poolId, String nodeId, String userName, NodeUpdateUserParameter nodeUpdateUserParameter, ComputeNodeUpdateUserOptions computeNodeUpdateUserOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (userName == null) {
            throw new IllegalArgumentException("Parameter userName is required and cannot be null.");
        }
        if (nodeUpdateUserParameter == null) {
            throw new IllegalArgumentException("Parameter nodeUpdateUserParameter is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(nodeUpdateUserParameter);
        Validator.validate(computeNodeUpdateUserOptions);
        Integer timeout = null;
        if (computeNodeUpdateUserOptions != null) {
            timeout = computeNodeUpdateUserOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeUpdateUserOptions != null) {
            clientRequestId = computeNodeUpdateUserOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeUpdateUserOptions != null) {
            returnClientRequestId = computeNodeUpdateUserOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeUpdateUserOptions != null) {
            ocpDate = computeNodeUpdateUserOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.updateUser(poolId, nodeId, userName, nodeUpdateUserParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders> clientResponse = updateUserDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, ComputeNodeUpdateUserHeaders> updateUserDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Void, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeUpdateUserHeaders.class);
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the ComputeNode object if successful.
     */
    public ComputeNode get(String poolId, String nodeId) {
        return getWithServiceResponseAsync(poolId, nodeId).toBlocking().single().body();
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<ComputeNode> getAsync(String poolId, String nodeId, final ServiceCallback<ComputeNode> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getWithServiceResponseAsync(poolId, nodeId), serviceCallback);
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNode object
     */
    public Observable<ComputeNode> getAsync(String poolId, String nodeId) {
        return getWithServiceResponseAsync(poolId, nodeId).map(new Func1<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>, ComputeNode>() {
            @Override
            public ComputeNode call(ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNode object
     */
    public Observable<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>> getWithServiceResponseAsync(String poolId, String nodeId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeGetOptions computeNodeGetOptions = null;
        String select = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.get(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), select, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders> clientResponse = getDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @param computeNodeGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the ComputeNode object if successful.
     */
    public ComputeNode get(String poolId, String nodeId, ComputeNodeGetOptions computeNodeGetOptions) {
        return getWithServiceResponseAsync(poolId, nodeId, computeNodeGetOptions).toBlocking().single().body();
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @param computeNodeGetOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<ComputeNode> getAsync(String poolId, String nodeId, ComputeNodeGetOptions computeNodeGetOptions, final ServiceCallback<ComputeNode> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getWithServiceResponseAsync(poolId, nodeId, computeNodeGetOptions), serviceCallback);
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @param computeNodeGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNode object
     */
    public Observable<ComputeNode> getAsync(String poolId, String nodeId, ComputeNodeGetOptions computeNodeGetOptions) {
        return getWithServiceResponseAsync(poolId, nodeId, computeNodeGetOptions).map(new Func1<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>, ComputeNode>() {
            @Override
            public ComputeNode call(ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets information about the specified Compute Node.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to get information about.
     * @param computeNodeGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNode object
     */
    public Observable<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>> getWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeGetOptions computeNodeGetOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeGetOptions);
        String select = null;
        if (computeNodeGetOptions != null) {
            select = computeNodeGetOptions.select();
        }
        Integer timeout = null;
        if (computeNodeGetOptions != null) {
            timeout = computeNodeGetOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeGetOptions != null) {
            clientRequestId = computeNodeGetOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeGetOptions != null) {
            returnClientRequestId = computeNodeGetOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeGetOptions != null) {
            ocpDate = computeNodeGetOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.get(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), select, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders> clientResponse = getDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<ComputeNode, ComputeNodeGetHeaders> getDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<ComputeNode, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<ComputeNode>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeGetHeaders.class);
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void reboot(String poolId, String nodeId) {
        rebootWithServiceResponseAsync(poolId, nodeId).toBlocking().single().body();
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> rebootAsync(String poolId, String nodeId, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(rebootWithServiceResponseAsync(poolId, nodeId), serviceCallback);
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> rebootAsync(String poolId, String nodeId) {
        return rebootWithServiceResponseAsync(poolId, nodeId).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>> rebootWithServiceResponseAsync(String poolId, String nodeId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeRebootOption nodeRebootOption = null;
        final ComputeNodeRebootOptions computeNodeRebootOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        NodeRebootParameter nodeRebootParameter = new NodeRebootParameter();
        nodeRebootParameter.withNodeRebootOption(null);
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.reboot(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, nodeRebootParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders> clientResponse = rebootDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeRebootOption When to reboot the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeRebootOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void reboot(String poolId, String nodeId, ComputeNodeRebootOption nodeRebootOption, ComputeNodeRebootOptions computeNodeRebootOptions) {
        rebootWithServiceResponseAsync(poolId, nodeId, nodeRebootOption, computeNodeRebootOptions).toBlocking().single().body();
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeRebootOption When to reboot the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeRebootOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> rebootAsync(String poolId, String nodeId, ComputeNodeRebootOption nodeRebootOption, ComputeNodeRebootOptions computeNodeRebootOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(rebootWithServiceResponseAsync(poolId, nodeId, nodeRebootOption, computeNodeRebootOptions), serviceCallback);
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeRebootOption When to reboot the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeRebootOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> rebootAsync(String poolId, String nodeId, ComputeNodeRebootOption nodeRebootOption, ComputeNodeRebootOptions computeNodeRebootOptions) {
        return rebootWithServiceResponseAsync(poolId, nodeId, nodeRebootOption, computeNodeRebootOptions).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Restarts the specified Compute Node.
     * You can restart a Compute Node only if it is in an idle or running state.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeRebootOption When to reboot the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeRebootOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>> rebootWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeRebootOption nodeRebootOption, ComputeNodeRebootOptions computeNodeRebootOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeRebootOptions);
        Integer timeout = null;
        if (computeNodeRebootOptions != null) {
            timeout = computeNodeRebootOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeRebootOptions != null) {
            clientRequestId = computeNodeRebootOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeRebootOptions != null) {
            returnClientRequestId = computeNodeRebootOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeRebootOptions != null) {
            ocpDate = computeNodeRebootOptions.ocpDate();
        }
        NodeRebootParameter nodeRebootParameter = null;
        if (nodeRebootOption != null) {
            nodeRebootParameter = new NodeRebootParameter();
            nodeRebootParameter.withNodeRebootOption(nodeRebootOption);
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.reboot(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, nodeRebootParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders> clientResponse = rebootDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, ComputeNodeRebootHeaders> rebootDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Void, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(202, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeRebootHeaders.class);
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void reimage(String poolId, String nodeId) {
        reimageWithServiceResponseAsync(poolId, nodeId).toBlocking().single().body();
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> reimageAsync(String poolId, String nodeId, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(reimageWithServiceResponseAsync(poolId, nodeId), serviceCallback);
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> reimageAsync(String poolId, String nodeId) {
        return reimageWithServiceResponseAsync(poolId, nodeId).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>> reimageWithServiceResponseAsync(String poolId, String nodeId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeReimageOption nodeReimageOption = null;
        final ComputeNodeReimageOptions computeNodeReimageOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        NodeReimageParameter nodeReimageParameter = new NodeReimageParameter();
        nodeReimageParameter.withNodeReimageOption(null);
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.reimage(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, nodeReimageParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders> clientResponse = reimageDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeReimageOption When to reimage the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeReimageOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void reimage(String poolId, String nodeId, ComputeNodeReimageOption nodeReimageOption, ComputeNodeReimageOptions computeNodeReimageOptions) {
        reimageWithServiceResponseAsync(poolId, nodeId, nodeReimageOption, computeNodeReimageOptions).toBlocking().single().body();
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeReimageOption When to reimage the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeReimageOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> reimageAsync(String poolId, String nodeId, ComputeNodeReimageOption nodeReimageOption, ComputeNodeReimageOptions computeNodeReimageOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(reimageWithServiceResponseAsync(poolId, nodeId, nodeReimageOption, computeNodeReimageOptions), serviceCallback);
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeReimageOption When to reimage the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeReimageOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> reimageAsync(String poolId, String nodeId, ComputeNodeReimageOption nodeReimageOption, ComputeNodeReimageOptions computeNodeReimageOptions) {
        return reimageWithServiceResponseAsync(poolId, nodeId, nodeReimageOption, computeNodeReimageOptions).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Reinstalls the operating system on the specified Compute Node.
     * You can reinstall the operating system on a Compute Node only if it is in an idle or running state. This API can be invoked only on Pools created with the cloud service configuration property.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node that you want to restart.
     * @param nodeReimageOption When to reimage the Compute Node and what to do with currently running Tasks. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion', 'retainedData'
     * @param computeNodeReimageOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>> reimageWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeReimageOption nodeReimageOption, ComputeNodeReimageOptions computeNodeReimageOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeReimageOptions);
        Integer timeout = null;
        if (computeNodeReimageOptions != null) {
            timeout = computeNodeReimageOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeReimageOptions != null) {
            clientRequestId = computeNodeReimageOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeReimageOptions != null) {
            returnClientRequestId = computeNodeReimageOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeReimageOptions != null) {
            ocpDate = computeNodeReimageOptions.ocpDate();
        }
        NodeReimageParameter nodeReimageParameter = null;
        if (nodeReimageOption != null) {
            nodeReimageParameter = new NodeReimageParameter();
            nodeReimageParameter.withNodeReimageOption(nodeReimageOption);
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.reimage(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, nodeReimageParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders> clientResponse = reimageDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, ComputeNodeReimageHeaders> reimageDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Void, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(202, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeReimageHeaders.class);
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void disableScheduling(String poolId, String nodeId) {
        disableSchedulingWithServiceResponseAsync(poolId, nodeId).toBlocking().single().body();
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> disableSchedulingAsync(String poolId, String nodeId, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(disableSchedulingWithServiceResponseAsync(poolId, nodeId), serviceCallback);
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> disableSchedulingAsync(String poolId, String nodeId) {
        return disableSchedulingWithServiceResponseAsync(poolId, nodeId).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>> disableSchedulingWithServiceResponseAsync(String poolId, String nodeId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final DisableComputeNodeSchedulingOption nodeDisableSchedulingOption = null;
        final ComputeNodeDisableSchedulingOptions computeNodeDisableSchedulingOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        NodeDisableSchedulingParameter nodeDisableSchedulingParameter = new NodeDisableSchedulingParameter();
        nodeDisableSchedulingParameter.withNodeDisableSchedulingOption(null);
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.disableScheduling(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, nodeDisableSchedulingParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders> clientResponse = disableSchedulingDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @param nodeDisableSchedulingOption What to do with currently running Tasks when disabling Task scheduling on the Compute Node. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion'
     * @param computeNodeDisableSchedulingOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void disableScheduling(String poolId, String nodeId, DisableComputeNodeSchedulingOption nodeDisableSchedulingOption, ComputeNodeDisableSchedulingOptions computeNodeDisableSchedulingOptions) {
        disableSchedulingWithServiceResponseAsync(poolId, nodeId, nodeDisableSchedulingOption, computeNodeDisableSchedulingOptions).toBlocking().single().body();
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @param nodeDisableSchedulingOption What to do with currently running Tasks when disabling Task scheduling on the Compute Node. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion'
     * @param computeNodeDisableSchedulingOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> disableSchedulingAsync(String poolId, String nodeId, DisableComputeNodeSchedulingOption nodeDisableSchedulingOption, ComputeNodeDisableSchedulingOptions computeNodeDisableSchedulingOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(disableSchedulingWithServiceResponseAsync(poolId, nodeId, nodeDisableSchedulingOption, computeNodeDisableSchedulingOptions), serviceCallback);
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @param nodeDisableSchedulingOption What to do with currently running Tasks when disabling Task scheduling on the Compute Node. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion'
     * @param computeNodeDisableSchedulingOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> disableSchedulingAsync(String poolId, String nodeId, DisableComputeNodeSchedulingOption nodeDisableSchedulingOption, ComputeNodeDisableSchedulingOptions computeNodeDisableSchedulingOptions) {
        return disableSchedulingWithServiceResponseAsync(poolId, nodeId, nodeDisableSchedulingOption, computeNodeDisableSchedulingOptions).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Disables Task scheduling on the specified Compute Node.
     * You can disable Task scheduling on a Compute Node only if its current scheduling state is enabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to disable Task scheduling.
     * @param nodeDisableSchedulingOption What to do with currently running Tasks when disabling Task scheduling on the Compute Node. The default value is requeue. Possible values include: 'requeue', 'terminate', 'taskCompletion'
     * @param computeNodeDisableSchedulingOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>> disableSchedulingWithServiceResponseAsync(String poolId, String nodeId, DisableComputeNodeSchedulingOption nodeDisableSchedulingOption, ComputeNodeDisableSchedulingOptions computeNodeDisableSchedulingOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeDisableSchedulingOptions);
        Integer timeout = null;
        if (computeNodeDisableSchedulingOptions != null) {
            timeout = computeNodeDisableSchedulingOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeDisableSchedulingOptions != null) {
            clientRequestId = computeNodeDisableSchedulingOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeDisableSchedulingOptions != null) {
            returnClientRequestId = computeNodeDisableSchedulingOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeDisableSchedulingOptions != null) {
            ocpDate = computeNodeDisableSchedulingOptions.ocpDate();
        }
        NodeDisableSchedulingParameter nodeDisableSchedulingParameter = null;
        if (nodeDisableSchedulingOption != null) {
            nodeDisableSchedulingParameter = new NodeDisableSchedulingParameter();
            nodeDisableSchedulingParameter.withNodeDisableSchedulingOption(nodeDisableSchedulingOption);
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.disableScheduling(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, nodeDisableSchedulingParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders> clientResponse = disableSchedulingDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, ComputeNodeDisableSchedulingHeaders> disableSchedulingDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Void, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeDisableSchedulingHeaders.class);
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void enableScheduling(String poolId, String nodeId) {
        enableSchedulingWithServiceResponseAsync(poolId, nodeId).toBlocking().single().body();
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> enableSchedulingAsync(String poolId, String nodeId, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(enableSchedulingWithServiceResponseAsync(poolId, nodeId), serviceCallback);
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> enableSchedulingAsync(String poolId, String nodeId) {
        return enableSchedulingWithServiceResponseAsync(poolId, nodeId).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>> enableSchedulingWithServiceResponseAsync(String poolId, String nodeId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeEnableSchedulingOptions computeNodeEnableSchedulingOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.enableScheduling(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders> clientResponse = enableSchedulingDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @param computeNodeEnableSchedulingOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void enableScheduling(String poolId, String nodeId, ComputeNodeEnableSchedulingOptions computeNodeEnableSchedulingOptions) {
        enableSchedulingWithServiceResponseAsync(poolId, nodeId, computeNodeEnableSchedulingOptions).toBlocking().single().body();
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @param computeNodeEnableSchedulingOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<Void> enableSchedulingAsync(String poolId, String nodeId, ComputeNodeEnableSchedulingOptions computeNodeEnableSchedulingOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(enableSchedulingWithServiceResponseAsync(poolId, nodeId, computeNodeEnableSchedulingOptions), serviceCallback);
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @param computeNodeEnableSchedulingOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> enableSchedulingAsync(String poolId, String nodeId, ComputeNodeEnableSchedulingOptions computeNodeEnableSchedulingOptions) {
        return enableSchedulingWithServiceResponseAsync(poolId, nodeId, computeNodeEnableSchedulingOptions).map(new Func1<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Enables Task scheduling on the specified Compute Node.
     * You can enable Task scheduling on a Compute Node only if its current scheduling state is disabled.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node on which you want to enable Task scheduling.
     * @param computeNodeEnableSchedulingOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>> enableSchedulingWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeEnableSchedulingOptions computeNodeEnableSchedulingOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeEnableSchedulingOptions);
        Integer timeout = null;
        if (computeNodeEnableSchedulingOptions != null) {
            timeout = computeNodeEnableSchedulingOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeEnableSchedulingOptions != null) {
            clientRequestId = computeNodeEnableSchedulingOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeEnableSchedulingOptions != null) {
            returnClientRequestId = computeNodeEnableSchedulingOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeEnableSchedulingOptions != null) {
            ocpDate = computeNodeEnableSchedulingOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.enableScheduling(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders> clientResponse = enableSchedulingDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, ComputeNodeEnableSchedulingHeaders> enableSchedulingDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Void, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeEnableSchedulingHeaders.class);
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the ComputeNodeGetRemoteLoginSettingsResult object if successful.
     */
    public ComputeNodeGetRemoteLoginSettingsResult getRemoteLoginSettings(String poolId, String nodeId) {
        return getRemoteLoginSettingsWithServiceResponseAsync(poolId, nodeId).toBlocking().single().body();
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<ComputeNodeGetRemoteLoginSettingsResult> getRemoteLoginSettingsAsync(String poolId, String nodeId, final ServiceCallback<ComputeNodeGetRemoteLoginSettingsResult> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getRemoteLoginSettingsWithServiceResponseAsync(poolId, nodeId), serviceCallback);
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNodeGetRemoteLoginSettingsResult object
     */
    public Observable<ComputeNodeGetRemoteLoginSettingsResult> getRemoteLoginSettingsAsync(String poolId, String nodeId) {
        return getRemoteLoginSettingsWithServiceResponseAsync(poolId, nodeId).map(new Func1<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>, ComputeNodeGetRemoteLoginSettingsResult>() {
            @Override
            public ComputeNodeGetRemoteLoginSettingsResult call(ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNodeGetRemoteLoginSettingsResult object
     */
    public Observable<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>> getRemoteLoginSettingsWithServiceResponseAsync(String poolId, String nodeId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeGetRemoteLoginSettingsOptions computeNodeGetRemoteLoginSettingsOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.getRemoteLoginSettings(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders> clientResponse = getRemoteLoginSettingsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @param computeNodeGetRemoteLoginSettingsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the ComputeNodeGetRemoteLoginSettingsResult object if successful.
     */
    public ComputeNodeGetRemoteLoginSettingsResult getRemoteLoginSettings(String poolId, String nodeId, ComputeNodeGetRemoteLoginSettingsOptions computeNodeGetRemoteLoginSettingsOptions) {
        return getRemoteLoginSettingsWithServiceResponseAsync(poolId, nodeId, computeNodeGetRemoteLoginSettingsOptions).toBlocking().single().body();
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @param computeNodeGetRemoteLoginSettingsOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<ComputeNodeGetRemoteLoginSettingsResult> getRemoteLoginSettingsAsync(String poolId, String nodeId, ComputeNodeGetRemoteLoginSettingsOptions computeNodeGetRemoteLoginSettingsOptions, final ServiceCallback<ComputeNodeGetRemoteLoginSettingsResult> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getRemoteLoginSettingsWithServiceResponseAsync(poolId, nodeId, computeNodeGetRemoteLoginSettingsOptions), serviceCallback);
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @param computeNodeGetRemoteLoginSettingsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNodeGetRemoteLoginSettingsResult object
     */
    public Observable<ComputeNodeGetRemoteLoginSettingsResult> getRemoteLoginSettingsAsync(String poolId, String nodeId, ComputeNodeGetRemoteLoginSettingsOptions computeNodeGetRemoteLoginSettingsOptions) {
        return getRemoteLoginSettingsWithServiceResponseAsync(poolId, nodeId, computeNodeGetRemoteLoginSettingsOptions).map(new Func1<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>, ComputeNodeGetRemoteLoginSettingsResult>() {
            @Override
            public ComputeNodeGetRemoteLoginSettingsResult call(ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets the settings required for remote login to a Compute Node.
     * Before you can remotely login to a Compute Node using the remote login settings, you must create a user Account on the Compute Node. This API can be invoked only on Pools created with the virtual machine configuration property. For Pools created with a cloud service configuration, see the GetRemoteDesktop API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which to obtain the remote login settings.
     * @param computeNodeGetRemoteLoginSettingsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ComputeNodeGetRemoteLoginSettingsResult object
     */
    public Observable<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>> getRemoteLoginSettingsWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeGetRemoteLoginSettingsOptions computeNodeGetRemoteLoginSettingsOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeGetRemoteLoginSettingsOptions);
        Integer timeout = null;
        if (computeNodeGetRemoteLoginSettingsOptions != null) {
            timeout = computeNodeGetRemoteLoginSettingsOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeGetRemoteLoginSettingsOptions != null) {
            clientRequestId = computeNodeGetRemoteLoginSettingsOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeGetRemoteLoginSettingsOptions != null) {
            returnClientRequestId = computeNodeGetRemoteLoginSettingsOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeGetRemoteLoginSettingsOptions != null) {
            ocpDate = computeNodeGetRemoteLoginSettingsOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.getRemoteLoginSettings(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders> clientResponse = getRemoteLoginSettingsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<ComputeNodeGetRemoteLoginSettingsResult, ComputeNodeGetRemoteLoginSettingsHeaders> getRemoteLoginSettingsDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<ComputeNodeGetRemoteLoginSettingsResult, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<ComputeNodeGetRemoteLoginSettingsResult>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeGetRemoteLoginSettingsHeaders.class);
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the InputStream object if successful.
     */
    public InputStream getRemoteDesktop(String poolId, String nodeId) {
        return getRemoteDesktopWithServiceResponseAsync(poolId, nodeId).toBlocking().single().body();
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<InputStream> getRemoteDesktopAsync(String poolId, String nodeId, final ServiceCallback<InputStream> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getRemoteDesktopWithServiceResponseAsync(poolId, nodeId), serviceCallback);
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the InputStream object
     */
    public Observable<InputStream> getRemoteDesktopAsync(String poolId, String nodeId) {
        return getRemoteDesktopWithServiceResponseAsync(poolId, nodeId).map(new Func1<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>, InputStream>() {
            @Override
            public InputStream call(ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the InputStream object
     */
    public Observable<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>> getRemoteDesktopWithServiceResponseAsync(String poolId, String nodeId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeGetRemoteDesktopOptions computeNodeGetRemoteDesktopOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.getRemoteDesktop(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders> clientResponse = getRemoteDesktopDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @param computeNodeGetRemoteDesktopOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the InputStream object if successful.
     */
    public InputStream getRemoteDesktop(String poolId, String nodeId, ComputeNodeGetRemoteDesktopOptions computeNodeGetRemoteDesktopOptions) {
        return getRemoteDesktopWithServiceResponseAsync(poolId, nodeId, computeNodeGetRemoteDesktopOptions).toBlocking().single().body();
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @param computeNodeGetRemoteDesktopOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<InputStream> getRemoteDesktopAsync(String poolId, String nodeId, ComputeNodeGetRemoteDesktopOptions computeNodeGetRemoteDesktopOptions, final ServiceCallback<InputStream> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getRemoteDesktopWithServiceResponseAsync(poolId, nodeId, computeNodeGetRemoteDesktopOptions), serviceCallback);
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @param computeNodeGetRemoteDesktopOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the InputStream object
     */
    public Observable<InputStream> getRemoteDesktopAsync(String poolId, String nodeId, ComputeNodeGetRemoteDesktopOptions computeNodeGetRemoteDesktopOptions) {
        return getRemoteDesktopWithServiceResponseAsync(poolId, nodeId, computeNodeGetRemoteDesktopOptions).map(new Func1<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>, InputStream>() {
            @Override
            public InputStream call(ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets the Remote Desktop Protocol file for the specified Compute Node.
     * Before you can access a Compute Node by using the RDP file, you must create a user Account on the Compute Node. This API can only be invoked on Pools created with a cloud service configuration. For Pools created with a virtual machine configuration, see the GetRemoteLoginSettings API.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node for which you want to get the Remote Desktop Protocol file.
     * @param computeNodeGetRemoteDesktopOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the InputStream object
     */
    public Observable<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>> getRemoteDesktopWithServiceResponseAsync(String poolId, String nodeId, ComputeNodeGetRemoteDesktopOptions computeNodeGetRemoteDesktopOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeGetRemoteDesktopOptions);
        Integer timeout = null;
        if (computeNodeGetRemoteDesktopOptions != null) {
            timeout = computeNodeGetRemoteDesktopOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeGetRemoteDesktopOptions != null) {
            clientRequestId = computeNodeGetRemoteDesktopOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeGetRemoteDesktopOptions != null) {
            returnClientRequestId = computeNodeGetRemoteDesktopOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeGetRemoteDesktopOptions != null) {
            ocpDate = computeNodeGetRemoteDesktopOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.getRemoteDesktop(poolId, nodeId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders> clientResponse = getRemoteDesktopDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<InputStream, ComputeNodeGetRemoteDesktopHeaders> getRemoteDesktopDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<InputStream, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<InputStream>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeGetRemoteDesktopHeaders.class);
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the UploadBatchServiceLogsResult object if successful.
     */
    public UploadBatchServiceLogsResult uploadBatchServiceLogs(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration) {
        return uploadBatchServiceLogsWithServiceResponseAsync(poolId, nodeId, uploadBatchServiceLogsConfiguration).toBlocking().single().body();
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<UploadBatchServiceLogsResult> uploadBatchServiceLogsAsync(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration, final ServiceCallback<UploadBatchServiceLogsResult> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(uploadBatchServiceLogsWithServiceResponseAsync(poolId, nodeId, uploadBatchServiceLogsConfiguration), serviceCallback);
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the UploadBatchServiceLogsResult object
     */
    public Observable<UploadBatchServiceLogsResult> uploadBatchServiceLogsAsync(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration) {
        return uploadBatchServiceLogsWithServiceResponseAsync(poolId, nodeId, uploadBatchServiceLogsConfiguration).map(new Func1<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>, UploadBatchServiceLogsResult>() {
            @Override
            public UploadBatchServiceLogsResult call(ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the UploadBatchServiceLogsResult object
     */
    public Observable<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>> uploadBatchServiceLogsWithServiceResponseAsync(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (uploadBatchServiceLogsConfiguration == null) {
            throw new IllegalArgumentException("Parameter uploadBatchServiceLogsConfiguration is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(uploadBatchServiceLogsConfiguration);
        final ComputeNodeUploadBatchServiceLogsOptions computeNodeUploadBatchServiceLogsOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.uploadBatchServiceLogs(poolId, nodeId, uploadBatchServiceLogsConfiguration, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders> clientResponse = uploadBatchServiceLogsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @param computeNodeUploadBatchServiceLogsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the UploadBatchServiceLogsResult object if successful.
     */
    public UploadBatchServiceLogsResult uploadBatchServiceLogs(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration, ComputeNodeUploadBatchServiceLogsOptions computeNodeUploadBatchServiceLogsOptions) {
        return uploadBatchServiceLogsWithServiceResponseAsync(poolId, nodeId, uploadBatchServiceLogsConfiguration, computeNodeUploadBatchServiceLogsOptions).toBlocking().single().body();
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @param computeNodeUploadBatchServiceLogsOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<UploadBatchServiceLogsResult> uploadBatchServiceLogsAsync(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration, ComputeNodeUploadBatchServiceLogsOptions computeNodeUploadBatchServiceLogsOptions, final ServiceCallback<UploadBatchServiceLogsResult> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(uploadBatchServiceLogsWithServiceResponseAsync(poolId, nodeId, uploadBatchServiceLogsConfiguration, computeNodeUploadBatchServiceLogsOptions), serviceCallback);
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @param computeNodeUploadBatchServiceLogsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the UploadBatchServiceLogsResult object
     */
    public Observable<UploadBatchServiceLogsResult> uploadBatchServiceLogsAsync(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration, ComputeNodeUploadBatchServiceLogsOptions computeNodeUploadBatchServiceLogsOptions) {
        return uploadBatchServiceLogsWithServiceResponseAsync(poolId, nodeId, uploadBatchServiceLogsConfiguration, computeNodeUploadBatchServiceLogsOptions).map(new Func1<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>, UploadBatchServiceLogsResult>() {
            @Override
            public UploadBatchServiceLogsResult call(ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Upload Azure Batch service log files from the specified Compute Node to Azure Blob Storage.
     * This is for gathering Azure Batch service log files in an automated fashion from Compute Nodes if you are experiencing an error and wish to escalate to Azure support. The Azure Batch service log files should be shared with Azure support to aid in debugging issues with the Batch service.
     *
     * @param poolId The ID of the Pool that contains the Compute Node.
     * @param nodeId The ID of the Compute Node from which you want to upload the Azure Batch service log files.
     * @param uploadBatchServiceLogsConfiguration The Azure Batch service log files upload configuration.
     * @param computeNodeUploadBatchServiceLogsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the UploadBatchServiceLogsResult object
     */
    public Observable<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>> uploadBatchServiceLogsWithServiceResponseAsync(String poolId, String nodeId, UploadBatchServiceLogsConfiguration uploadBatchServiceLogsConfiguration, ComputeNodeUploadBatchServiceLogsOptions computeNodeUploadBatchServiceLogsOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (nodeId == null) {
            throw new IllegalArgumentException("Parameter nodeId is required and cannot be null.");
        }
        if (uploadBatchServiceLogsConfiguration == null) {
            throw new IllegalArgumentException("Parameter uploadBatchServiceLogsConfiguration is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(uploadBatchServiceLogsConfiguration);
        Validator.validate(computeNodeUploadBatchServiceLogsOptions);
        Integer timeout = null;
        if (computeNodeUploadBatchServiceLogsOptions != null) {
            timeout = computeNodeUploadBatchServiceLogsOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeUploadBatchServiceLogsOptions != null) {
            clientRequestId = computeNodeUploadBatchServiceLogsOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeUploadBatchServiceLogsOptions != null) {
            returnClientRequestId = computeNodeUploadBatchServiceLogsOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeUploadBatchServiceLogsOptions != null) {
            ocpDate = computeNodeUploadBatchServiceLogsOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.uploadBatchServiceLogs(poolId, nodeId, uploadBatchServiceLogsConfiguration, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders> clientResponse = uploadBatchServiceLogsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<UploadBatchServiceLogsResult, ComputeNodeUploadBatchServiceLogsHeaders> uploadBatchServiceLogsDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<UploadBatchServiceLogsResult, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<UploadBatchServiceLogsResult>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeUploadBatchServiceLogsHeaders.class);
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ComputeNode&gt; object if successful.
     */
    public PagedList<ComputeNode> list(final String poolId) {
        ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response = listSinglePageAsync(poolId).toBlocking().single();
        return new PagedList<ComputeNode>(response.body()) {
            @Override
            public Page<ComputeNode> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ComputeNode>> listAsync(final String poolId, final ListOperationCallback<ComputeNode> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listSinglePageAsync(poolId),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<Page<ComputeNode>> listAsync(final String poolId) {
        return listWithServiceResponseAsync(poolId)
            .map(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Page<ComputeNode>>() {
                @Override
                public Page<ComputeNode> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listWithServiceResponseAsync(final String poolId) {
        return listSinglePageAsync(poolId)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ComputeNode&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listSinglePageAsync(final String poolId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ComputeNodeListOptions computeNodeListOptions = null;
        String filter = null;
        String select = null;
        Integer maxResults = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.list(poolId, this.client.apiVersion(), this.client.acceptLanguage(), filter, select, maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> result = listDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @param computeNodeListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ComputeNode&gt; object if successful.
     */
    public PagedList<ComputeNode> list(final String poolId, final ComputeNodeListOptions computeNodeListOptions) {
        ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response = listSinglePageAsync(poolId, computeNodeListOptions).toBlocking().single();
        return new PagedList<ComputeNode>(response.body()) {
            @Override
            public Page<ComputeNode> nextPage(String nextPageLink) {
                ComputeNodeListNextOptions computeNodeListNextOptions = null;
                if (computeNodeListOptions != null) {
                    computeNodeListNextOptions = new ComputeNodeListNextOptions();
                    computeNodeListNextOptions.withClientRequestId(computeNodeListOptions.clientRequestId());
                    computeNodeListNextOptions.withReturnClientRequestId(computeNodeListOptions.returnClientRequestId());
                    computeNodeListNextOptions.withOcpDate(computeNodeListOptions.ocpDate());
                }
                return listNextSinglePageAsync(nextPageLink, computeNodeListNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @param computeNodeListOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ComputeNode>> listAsync(final String poolId, final ComputeNodeListOptions computeNodeListOptions, final ListOperationCallback<ComputeNode> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listSinglePageAsync(poolId, computeNodeListOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(String nextPageLink) {
                    ComputeNodeListNextOptions computeNodeListNextOptions = null;
                    if (computeNodeListOptions != null) {
                        computeNodeListNextOptions = new ComputeNodeListNextOptions();
                        computeNodeListNextOptions.withClientRequestId(computeNodeListOptions.clientRequestId());
                        computeNodeListNextOptions.withReturnClientRequestId(computeNodeListOptions.returnClientRequestId());
                        computeNodeListNextOptions.withOcpDate(computeNodeListOptions.ocpDate());
                    }
                    return listNextSinglePageAsync(nextPageLink, computeNodeListNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @param computeNodeListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<Page<ComputeNode>> listAsync(final String poolId, final ComputeNodeListOptions computeNodeListOptions) {
        return listWithServiceResponseAsync(poolId, computeNodeListOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Page<ComputeNode>>() {
                @Override
                public Page<ComputeNode> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param poolId The ID of the Pool from which you want to list Compute Nodes.
     * @param computeNodeListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listWithServiceResponseAsync(final String poolId, final ComputeNodeListOptions computeNodeListOptions) {
        return listSinglePageAsync(poolId, computeNodeListOptions)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    ComputeNodeListNextOptions computeNodeListNextOptions = null;
                    if (computeNodeListOptions != null) {
                        computeNodeListNextOptions = new ComputeNodeListNextOptions();
                        computeNodeListNextOptions.withClientRequestId(computeNodeListOptions.clientRequestId());
                        computeNodeListNextOptions.withReturnClientRequestId(computeNodeListOptions.returnClientRequestId());
                        computeNodeListNextOptions.withOcpDate(computeNodeListOptions.ocpDate());
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, computeNodeListNextOptions));
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
    ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> * @param poolId The ID of the Pool from which you want to list Compute Nodes.
    ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> * @param computeNodeListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ComputeNode&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listSinglePageAsync(final String poolId, final ComputeNodeListOptions computeNodeListOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (poolId == null) {
            throw new IllegalArgumentException("Parameter poolId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(computeNodeListOptions);
        String filter = null;
        if (computeNodeListOptions != null) {
            filter = computeNodeListOptions.filter();
        }
        String select = null;
        if (computeNodeListOptions != null) {
            select = computeNodeListOptions.select();
        }
        Integer maxResults = null;
        if (computeNodeListOptions != null) {
            maxResults = computeNodeListOptions.maxResults();
        }
        Integer timeout = null;
        if (computeNodeListOptions != null) {
            timeout = computeNodeListOptions.timeout();
        }
        UUID clientRequestId = null;
        if (computeNodeListOptions != null) {
            clientRequestId = computeNodeListOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeListOptions != null) {
            returnClientRequestId = computeNodeListOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeListOptions != null) {
            ocpDate = computeNodeListOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.list(poolId, this.client.apiVersion(), this.client.acceptLanguage(), filter, select, maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> result = listDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> listDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<PageImpl<ComputeNode>, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<PageImpl<ComputeNode>>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeListHeaders.class);
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ComputeNode&gt; object if successful.
     */
    public PagedList<ComputeNode> listNext(final String nextPageLink) {
        ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response = listNextSinglePageAsync(nextPageLink).toBlocking().single();
        return new PagedList<ComputeNode>(response.body()) {
            @Override
            public Page<ComputeNode> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param serviceFuture the ServiceFuture object tracking the Retrofit calls
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ComputeNode>> listNextAsync(final String nextPageLink, final ServiceFuture<List<ComputeNode>> serviceFuture, final ListOperationCallback<ComputeNode> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listNextSinglePageAsync(nextPageLink),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<Page<ComputeNode>> listNextAsync(final String nextPageLink) {
        return listNextWithServiceResponseAsync(nextPageLink)
            .map(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Page<ComputeNode>>() {
                @Override
                public Page<ComputeNode> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listNextWithServiceResponseAsync(final String nextPageLink) {
        return listNextSinglePageAsync(nextPageLink)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ComputeNode&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listNextSinglePageAsync(final String nextPageLink) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        final ComputeNodeListNextOptions computeNodeListNextOptions = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        String nextUrl = String.format("%s", nextPageLink);
        return service.listNext(nextUrl, this.client.acceptLanguage(), clientRequestId, returnClientRequestId, ocpDateConverted, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> result = listNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param computeNodeListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ComputeNode&gt; object if successful.
     */
    public PagedList<ComputeNode> listNext(final String nextPageLink, final ComputeNodeListNextOptions computeNodeListNextOptions) {
        ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response = listNextSinglePageAsync(nextPageLink, computeNodeListNextOptions).toBlocking().single();
        return new PagedList<ComputeNode>(response.body()) {
            @Override
            public Page<ComputeNode> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, computeNodeListNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param computeNodeListNextOptions Additional parameters for the operation
     * @param serviceFuture the ServiceFuture object tracking the Retrofit calls
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ComputeNode>> listNextAsync(final String nextPageLink, final ComputeNodeListNextOptions computeNodeListNextOptions, final ServiceFuture<List<ComputeNode>> serviceFuture, final ListOperationCallback<ComputeNode> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listNextSinglePageAsync(nextPageLink, computeNodeListNextOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, computeNodeListNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param computeNodeListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<Page<ComputeNode>> listNextAsync(final String nextPageLink, final ComputeNodeListNextOptions computeNodeListNextOptions) {
        return listNextWithServiceResponseAsync(nextPageLink, computeNodeListNextOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Page<ComputeNode>>() {
                @Override
                public Page<ComputeNode> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param computeNodeListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ComputeNode&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listNextWithServiceResponseAsync(final String nextPageLink, final ComputeNodeListNextOptions computeNodeListNextOptions) {
        return listNextSinglePageAsync(nextPageLink, computeNodeListNextOptions)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, computeNodeListNextOptions));
                }
            });
    }

    /**
     * Lists the Compute Nodes in the specified Pool.
     *
    ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> * @param nextPageLink The NextLink from the previous successful call to List operation.
    ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> * @param computeNodeListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ComputeNode&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> listNextSinglePageAsync(final String nextPageLink, final ComputeNodeListNextOptions computeNodeListNextOptions) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        Validator.validate(computeNodeListNextOptions);
        UUID clientRequestId = null;
        if (computeNodeListNextOptions != null) {
            clientRequestId = computeNodeListNextOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (computeNodeListNextOptions != null) {
            returnClientRequestId = computeNodeListNextOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (computeNodeListNextOptions != null) {
            ocpDate = computeNodeListNextOptions.ocpDate();
        }
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        String nextUrl = String.format("%s", nextPageLink);
        return service.listNext(nextUrl, this.client.acceptLanguage(), clientRequestId, returnClientRequestId, ocpDateConverted, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> result = listNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ComputeNode>, ComputeNodeListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<PageImpl<ComputeNode>, ComputeNodeListHeaders> listNextDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<PageImpl<ComputeNode>, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<PageImpl<ComputeNode>>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ComputeNodeListHeaders.class);
    }

}
