/**
 * 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.Pools;
import com.google.common.base.Joiner;
import com.google.common.reflect.TypeToken;
import com.microsoft.azure.AzureServiceFuture;
import com.microsoft.azure.batch.protocol.models.AutoScaleRun;
import com.microsoft.azure.batch.protocol.models.BatchErrorException;
import com.microsoft.azure.batch.protocol.models.CloudPool;
import com.microsoft.azure.batch.protocol.models.NodeRemoveParameter;
import com.microsoft.azure.batch.protocol.models.PageImpl;
import com.microsoft.azure.batch.protocol.models.PoolAddHeaders;
import com.microsoft.azure.batch.protocol.models.PoolAddOptions;
import com.microsoft.azure.batch.protocol.models.PoolAddParameter;
import com.microsoft.azure.batch.protocol.models.PoolDeleteHeaders;
import com.microsoft.azure.batch.protocol.models.PoolDeleteOptions;
import com.microsoft.azure.batch.protocol.models.PoolDisableAutoScaleHeaders;
import com.microsoft.azure.batch.protocol.models.PoolDisableAutoScaleOptions;
import com.microsoft.azure.batch.protocol.models.PoolEnableAutoScaleHeaders;
import com.microsoft.azure.batch.protocol.models.PoolEnableAutoScaleOptions;
import com.microsoft.azure.batch.protocol.models.PoolEnableAutoScaleParameter;
import com.microsoft.azure.batch.protocol.models.PoolEvaluateAutoScaleHeaders;
import com.microsoft.azure.batch.protocol.models.PoolEvaluateAutoScaleOptions;
import com.microsoft.azure.batch.protocol.models.PoolEvaluateAutoScaleParameter;
import com.microsoft.azure.batch.protocol.models.PoolExistsHeaders;
import com.microsoft.azure.batch.protocol.models.PoolExistsOptions;
import com.microsoft.azure.batch.protocol.models.PoolGetHeaders;
import com.microsoft.azure.batch.protocol.models.PoolGetOptions;
import com.microsoft.azure.batch.protocol.models.PoolListHeaders;
import com.microsoft.azure.batch.protocol.models.PoolListNextOptions;
import com.microsoft.azure.batch.protocol.models.PoolListOptions;
import com.microsoft.azure.batch.protocol.models.PoolListUsageMetricsHeaders;
import com.microsoft.azure.batch.protocol.models.PoolListUsageMetricsNextOptions;
import com.microsoft.azure.batch.protocol.models.PoolListUsageMetricsOptions;
import com.microsoft.azure.batch.protocol.models.PoolPatchHeaders;
import com.microsoft.azure.batch.protocol.models.PoolPatchOptions;
import com.microsoft.azure.batch.protocol.models.PoolPatchParameter;
import com.microsoft.azure.batch.protocol.models.PoolRemoveNodesHeaders;
import com.microsoft.azure.batch.protocol.models.PoolRemoveNodesOptions;
import com.microsoft.azure.batch.protocol.models.PoolResizeHeaders;
import com.microsoft.azure.batch.protocol.models.PoolResizeOptions;
import com.microsoft.azure.batch.protocol.models.PoolResizeParameter;
import com.microsoft.azure.batch.protocol.models.PoolStopResizeHeaders;
import com.microsoft.azure.batch.protocol.models.PoolStopResizeOptions;
import com.microsoft.azure.batch.protocol.models.PoolUpdatePropertiesHeaders;
import com.microsoft.azure.batch.protocol.models.PoolUpdatePropertiesOptions;
import com.microsoft.azure.batch.protocol.models.PoolUpdatePropertiesParameter;
import com.microsoft.azure.batch.protocol.models.PoolUsageMetrics;
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.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.HEAD;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.HTTP;
import retrofit2.http.PATCH;
import retrofit2.http.Path;
import retrofit2.http.POST;
import retrofit2.http.Query;
import retrofit2.http.Url;
import retrofit2.Response;
import rx.functions.Func1;
import rx.Observable;

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

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

    /**
     * The interface defining all the services for Pools to be
     * used by Retrofit to perform actually REST calls.
     */
    interface PoolsService {
        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.Pools listUsageMetrics" })
        @GET("poolusagemetrics")
        Observable<Response<ResponseBody>> listUsageMetrics(@Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("starttime") DateTime startTime, @Query("endtime") DateTime endTime, @Query("$filter") String filter, @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; odata=minimalmetadata; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.Pools add" })
        @POST("pools")
        Observable<Response<ResponseBody>> add(@Body PoolAddParameter pool, @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.Pools list" })
        @GET("pools")
        Observable<Response<ResponseBody>> list(@Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("$filter") String filter, @Query("$select") String select, @Query("$expand") String expand, @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.Pools delete" })
        @HTTP(path = "pools/{poolId}", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> delete(@Path("poolId") String poolId, @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("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools exists" })
        @HEAD("pools/{poolId}")
        Observable<Response<Void>> exists(@Path("poolId") String poolId, @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("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools get" })
        @GET("pools/{poolId}")
        Observable<Response<ResponseBody>> get(@Path("poolId") String poolId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("$select") String select, @Query("$expand") String expand, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools patch" })
        @PATCH("pools/{poolId}")
        Observable<Response<ResponseBody>> patch(@Path("poolId") String poolId, @Body PoolPatchParameter poolPatchParameter, @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("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools disableAutoScale" })
        @POST("pools/{poolId}/disableautoscale")
        Observable<Response<ResponseBody>> disableAutoScale(@Path("poolId") String poolId, @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.Pools enableAutoScale" })
        @POST("pools/{poolId}/enableautoscale")
        Observable<Response<ResponseBody>> enableAutoScale(@Path("poolId") String poolId, @Body PoolEnableAutoScaleParameter poolEnableAutoScaleParameter, @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("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools evaluateAutoScale" })
        @POST("pools/{poolId}/evaluateautoscale")
        Observable<Response<ResponseBody>> evaluateAutoScale(@Path("poolId") String poolId, @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 PoolEvaluateAutoScaleParameter poolEvaluateAutoScaleParameter, @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.Pools resize" })
        @POST("pools/{poolId}/resize")
        Observable<Response<ResponseBody>> resize(@Path("poolId") String poolId, @Body PoolResizeParameter poolResizeParameter, @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("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools stopResize" })
        @POST("pools/{poolId}/stopresize")
        Observable<Response<ResponseBody>> stopResize(@Path("poolId") String poolId, @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("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools updateProperties" })
        @POST("pools/{poolId}/updateproperties")
        Observable<Response<ResponseBody>> updateProperties(@Path("poolId") String poolId, @Body PoolUpdatePropertiesParameter poolUpdatePropertiesParameter, @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.Pools removeNodes" })
        @POST("pools/{poolId}/removenodes")
        Observable<Response<ResponseBody>> removeNodes(@Path("poolId") String poolId, @Body NodeRemoveParameter nodeRemoveParameter, @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("If-Match") String ifMatch, @Header("If-None-Match") String ifNoneMatch, @Header("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @Header("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @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.Pools listUsageMetricsNext" })
        @GET
        Observable<Response<ResponseBody>> listUsageMetricsNext(@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);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.Pools 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);

    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @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;PoolUsageMetrics&gt; object if successful.
     */
    public PagedList<PoolUsageMetrics> listUsageMetrics() {
        ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response = listUsageMetricsSinglePageAsync().toBlocking().single();
        return new PagedList<PoolUsageMetrics>(response.body()) {
            @Override
            public Page<PoolUsageMetrics> nextPage(String nextPageLink) {
                return listUsageMetricsNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @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<PoolUsageMetrics>> listUsageMetricsAsync(final ListOperationCallback<PoolUsageMetrics> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listUsageMetricsSinglePageAsync(),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(String nextPageLink) {
                    return listUsageMetricsNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;PoolUsageMetrics&gt; object
     */
    public Observable<Page<PoolUsageMetrics>> listUsageMetricsAsync() {
        return listUsageMetricsWithServiceResponseAsync()
            .map(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Page<PoolUsageMetrics>>() {
                @Override
                public Page<PoolUsageMetrics> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;PoolUsageMetrics&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsWithServiceResponseAsync() {
        return listUsageMetricsSinglePageAsync()
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listUsageMetricsNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;PoolUsageMetrics&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsSinglePageAsync() {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() 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 PoolListUsageMetricsOptions poolListUsageMetricsOptions = null;
        DateTime startTime = null;
        DateTime endTime = null;
        String filter = 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.listUsageMetrics(this.client.apiVersion(), this.client.acceptLanguage(), startTime, endTime, filter, maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<PoolUsageMetrics>, PoolListUsageMetricsHeaders> result = listUsageMetricsDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param poolListUsageMetricsOptions 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;PoolUsageMetrics&gt; object if successful.
     */
    public PagedList<PoolUsageMetrics> listUsageMetrics(final PoolListUsageMetricsOptions poolListUsageMetricsOptions) {
        ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response = listUsageMetricsSinglePageAsync(poolListUsageMetricsOptions).toBlocking().single();
        return new PagedList<PoolUsageMetrics>(response.body()) {
            @Override
            public Page<PoolUsageMetrics> nextPage(String nextPageLink) {
                PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions = null;
                if (poolListUsageMetricsOptions != null) {
                    poolListUsageMetricsNextOptions = new PoolListUsageMetricsNextOptions();
                    poolListUsageMetricsNextOptions.withClientRequestId(poolListUsageMetricsOptions.clientRequestId());
                    poolListUsageMetricsNextOptions.withReturnClientRequestId(poolListUsageMetricsOptions.returnClientRequestId());
                    poolListUsageMetricsNextOptions.withOcpDate(poolListUsageMetricsOptions.ocpDate());
                }
                return listUsageMetricsNextSinglePageAsync(nextPageLink, poolListUsageMetricsNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param poolListUsageMetricsOptions 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<PoolUsageMetrics>> listUsageMetricsAsync(final PoolListUsageMetricsOptions poolListUsageMetricsOptions, final ListOperationCallback<PoolUsageMetrics> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listUsageMetricsSinglePageAsync(poolListUsageMetricsOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(String nextPageLink) {
                    PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions = null;
                    if (poolListUsageMetricsOptions != null) {
                        poolListUsageMetricsNextOptions = new PoolListUsageMetricsNextOptions();
                        poolListUsageMetricsNextOptions.withClientRequestId(poolListUsageMetricsOptions.clientRequestId());
                        poolListUsageMetricsNextOptions.withReturnClientRequestId(poolListUsageMetricsOptions.returnClientRequestId());
                        poolListUsageMetricsNextOptions.withOcpDate(poolListUsageMetricsOptions.ocpDate());
                    }
                    return listUsageMetricsNextSinglePageAsync(nextPageLink, poolListUsageMetricsNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param poolListUsageMetricsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;PoolUsageMetrics&gt; object
     */
    public Observable<Page<PoolUsageMetrics>> listUsageMetricsAsync(final PoolListUsageMetricsOptions poolListUsageMetricsOptions) {
        return listUsageMetricsWithServiceResponseAsync(poolListUsageMetricsOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Page<PoolUsageMetrics>>() {
                @Override
                public Page<PoolUsageMetrics> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param poolListUsageMetricsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;PoolUsageMetrics&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsWithServiceResponseAsync(final PoolListUsageMetricsOptions poolListUsageMetricsOptions) {
        return listUsageMetricsSinglePageAsync(poolListUsageMetricsOptions)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions = null;
                    if (poolListUsageMetricsOptions != null) {
                        poolListUsageMetricsNextOptions = new PoolListUsageMetricsNextOptions();
                        poolListUsageMetricsNextOptions.withClientRequestId(poolListUsageMetricsOptions.clientRequestId());
                        poolListUsageMetricsNextOptions.withReturnClientRequestId(poolListUsageMetricsOptions.returnClientRequestId());
                        poolListUsageMetricsNextOptions.withOcpDate(poolListUsageMetricsOptions.ocpDate());
                    }
                    return Observable.just(page).concatWith(listUsageMetricsNextWithServiceResponseAsync(nextPageLink, poolListUsageMetricsNextOptions));
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
    ServiceResponseWithHeaders<PageImpl<PoolUsageMetrics>, PoolListUsageMetricsHeaders> * @param poolListUsageMetricsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;PoolUsageMetrics&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsSinglePageAsync(final PoolListUsageMetricsOptions poolListUsageMetricsOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() 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(poolListUsageMetricsOptions);
        DateTime startTime = null;
        if (poolListUsageMetricsOptions != null) {
            startTime = poolListUsageMetricsOptions.startTime();
        }
        DateTime endTime = null;
        if (poolListUsageMetricsOptions != null) {
            endTime = poolListUsageMetricsOptions.endTime();
        }
        String filter = null;
        if (poolListUsageMetricsOptions != null) {
            filter = poolListUsageMetricsOptions.filter();
        }
        Integer maxResults = null;
        if (poolListUsageMetricsOptions != null) {
            maxResults = poolListUsageMetricsOptions.maxResults();
        }
        Integer timeout = null;
        if (poolListUsageMetricsOptions != null) {
            timeout = poolListUsageMetricsOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolListUsageMetricsOptions != null) {
            clientRequestId = poolListUsageMetricsOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolListUsageMetricsOptions != null) {
            returnClientRequestId = poolListUsageMetricsOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolListUsageMetricsOptions != null) {
            ocpDate = poolListUsageMetricsOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.listUsageMetrics(this.client.apiVersion(), this.client.acceptLanguage(), startTime, endTime, filter, maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<PoolUsageMetrics>, PoolListUsageMetricsHeaders> result = listUsageMetricsDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @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 add(PoolAddParameter pool) {
        addWithServiceResponseAsync(pool).toBlocking().single().body();
    }

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @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> addAsync(PoolAddParameter pool, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(addWithServiceResponseAsync(pool), serviceCallback);
    }

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> addAsync(PoolAddParameter pool) {
        return addWithServiceResponseAsync(pool).map(new Func1<ServiceResponseWithHeaders<Void, PoolAddHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolAddHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolAddHeaders>> addWithServiceResponseAsync(PoolAddParameter pool) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (pool == null) {
            throw new IllegalArgumentException("Parameter pool 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(pool);
        final PoolAddOptions poolAddOptions = 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.add(pool, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolAddHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolAddHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolAddHeaders> clientResponse = addDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @param poolAddOptions 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 add(PoolAddParameter pool, PoolAddOptions poolAddOptions) {
        addWithServiceResponseAsync(pool, poolAddOptions).toBlocking().single().body();
    }

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @param poolAddOptions 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> addAsync(PoolAddParameter pool, PoolAddOptions poolAddOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(addWithServiceResponseAsync(pool, poolAddOptions), serviceCallback);
    }

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @param poolAddOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> addAsync(PoolAddParameter pool, PoolAddOptions poolAddOptions) {
        return addWithServiceResponseAsync(pool, poolAddOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolAddHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolAddHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Adds a Pool to the specified Account.
     * When naming Pools, avoid including sensitive information such as user names or secret project names. This information may appear in telemetry logs accessible to Microsoft Support engineers.
     *
     * @param pool The Pool to be added.
     * @param poolAddOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolAddHeaders>> addWithServiceResponseAsync(PoolAddParameter pool, PoolAddOptions poolAddOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (pool == null) {
            throw new IllegalArgumentException("Parameter pool 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(pool);
        Validator.validate(poolAddOptions);
        Integer timeout = null;
        if (poolAddOptions != null) {
            timeout = poolAddOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolAddOptions != null) {
            clientRequestId = poolAddOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolAddOptions != null) {
            returnClientRequestId = poolAddOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolAddOptions != null) {
            ocpDate = poolAddOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.add(pool, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolAddHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolAddHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolAddHeaders> clientResponse = addDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolAddHeaders> addDelegate(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, PoolAddHeaders.class);
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @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;CloudPool&gt; object if successful.
     */
    public PagedList<CloudPool> list() {
        ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response = listSinglePageAsync().toBlocking().single();
        return new PagedList<CloudPool>(response.body()) {
            @Override
            public Page<CloudPool> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @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<CloudPool>> listAsync(final ListOperationCallback<CloudPool> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listSinglePageAsync(),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;CloudPool&gt; object
     */
    public Observable<Page<CloudPool>> listAsync() {
        return listWithServiceResponseAsync()
            .map(new Func1<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>, Page<CloudPool>>() {
                @Override
                public Page<CloudPool> call(ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;CloudPool&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> listWithServiceResponseAsync() {
        return listSinglePageAsync()
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;CloudPool&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> listSinglePageAsync() {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() 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 PoolListOptions poolListOptions = null;
        String filter = null;
        String select = null;
        String expand = 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(this.client.apiVersion(), this.client.acceptLanguage(), filter, select, expand, maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<CloudPool>, PoolListHeaders> result = listDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param poolListOptions 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;CloudPool&gt; object if successful.
     */
    public PagedList<CloudPool> list(final PoolListOptions poolListOptions) {
        ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response = listSinglePageAsync(poolListOptions).toBlocking().single();
        return new PagedList<CloudPool>(response.body()) {
            @Override
            public Page<CloudPool> nextPage(String nextPageLink) {
                PoolListNextOptions poolListNextOptions = null;
                if (poolListOptions != null) {
                    poolListNextOptions = new PoolListNextOptions();
                    poolListNextOptions.withClientRequestId(poolListOptions.clientRequestId());
                    poolListNextOptions.withReturnClientRequestId(poolListOptions.returnClientRequestId());
                    poolListNextOptions.withOcpDate(poolListOptions.ocpDate());
                }
                return listNextSinglePageAsync(nextPageLink, poolListNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param poolListOptions 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<CloudPool>> listAsync(final PoolListOptions poolListOptions, final ListOperationCallback<CloudPool> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listSinglePageAsync(poolListOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(String nextPageLink) {
                    PoolListNextOptions poolListNextOptions = null;
                    if (poolListOptions != null) {
                        poolListNextOptions = new PoolListNextOptions();
                        poolListNextOptions.withClientRequestId(poolListOptions.clientRequestId());
                        poolListNextOptions.withReturnClientRequestId(poolListOptions.returnClientRequestId());
                        poolListNextOptions.withOcpDate(poolListOptions.ocpDate());
                    }
                    return listNextSinglePageAsync(nextPageLink, poolListNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param poolListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;CloudPool&gt; object
     */
    public Observable<Page<CloudPool>> listAsync(final PoolListOptions poolListOptions) {
        return listWithServiceResponseAsync(poolListOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>, Page<CloudPool>>() {
                @Override
                public Page<CloudPool> call(ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param poolListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;CloudPool&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> listWithServiceResponseAsync(final PoolListOptions poolListOptions) {
        return listSinglePageAsync(poolListOptions)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    PoolListNextOptions poolListNextOptions = null;
                    if (poolListOptions != null) {
                        poolListNextOptions = new PoolListNextOptions();
                        poolListNextOptions.withClientRequestId(poolListOptions.clientRequestId());
                        poolListNextOptions.withReturnClientRequestId(poolListOptions.returnClientRequestId());
                        poolListNextOptions.withOcpDate(poolListOptions.ocpDate());
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, poolListNextOptions));
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
    ServiceResponseWithHeaders<PageImpl<CloudPool>, PoolListHeaders> * @param poolListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;CloudPool&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> listSinglePageAsync(final PoolListOptions poolListOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() 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(poolListOptions);
        String filter = null;
        if (poolListOptions != null) {
            filter = poolListOptions.filter();
        }
        String select = null;
        if (poolListOptions != null) {
            select = poolListOptions.select();
        }
        String expand = null;
        if (poolListOptions != null) {
            expand = poolListOptions.expand();
        }
        Integer maxResults = null;
        if (poolListOptions != null) {
            maxResults = poolListOptions.maxResults();
        }
        Integer timeout = null;
        if (poolListOptions != null) {
            timeout = poolListOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolListOptions != null) {
            clientRequestId = poolListOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolListOptions != null) {
            returnClientRequestId = poolListOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolListOptions != null) {
            ocpDate = poolListOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.list(this.client.apiVersion(), this.client.acceptLanguage(), filter, select, expand, maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<CloudPool>, PoolListHeaders> result = listDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool 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 delete(String poolId) {
        deleteWithServiceResponseAsync(poolId).toBlocking().single().body();
    }

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool 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> deleteAsync(String poolId, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(deleteWithServiceResponseAsync(poolId), serviceCallback);
    }

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> deleteAsync(String poolId) {
        return deleteWithServiceResponseAsync(poolId).map(new Func1<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolDeleteHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>> deleteWithServiceResponseAsync(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 PoolDeleteOptions poolDeleteOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.delete(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolDeleteHeaders> clientResponse = deleteDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool to delete.
     * @param poolDeleteOptions 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 delete(String poolId, PoolDeleteOptions poolDeleteOptions) {
        deleteWithServiceResponseAsync(poolId, poolDeleteOptions).toBlocking().single().body();
    }

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool to delete.
     * @param poolDeleteOptions 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> deleteAsync(String poolId, PoolDeleteOptions poolDeleteOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(deleteWithServiceResponseAsync(poolId, poolDeleteOptions), serviceCallback);
    }

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool to delete.
     * @param poolDeleteOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> deleteAsync(String poolId, PoolDeleteOptions poolDeleteOptions) {
        return deleteWithServiceResponseAsync(poolId, poolDeleteOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolDeleteHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes a Pool from the specified Account.
     * When you request that a Pool be deleted, the following actions occur: the Pool state is set to deleting; any ongoing resize operation on the Pool are stopped; the Batch service starts resizing the Pool to zero Compute Nodes; any Tasks running on existing Compute Nodes are terminated and requeued (as if a resize Pool operation had been requested with the default requeue option); finally, the Pool is removed from the system. Because running Tasks are requeued, the user can rerun these Tasks by updating their Job to target a different Pool. The Tasks can then run on the new Pool. If you want to override the requeue behavior, then you should call resize Pool explicitly to shrink the Pool to zero size before deleting the Pool. If you call an Update, Patch or Delete API on a Pool in the deleting state, it will fail with HTTP status code 409 with error code PoolBeingDeleted.
     *
     * @param poolId The ID of the Pool to delete.
     * @param poolDeleteOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>> deleteWithServiceResponseAsync(String poolId, PoolDeleteOptions poolDeleteOptions) {
        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(poolDeleteOptions);
        Integer timeout = null;
        if (poolDeleteOptions != null) {
            timeout = poolDeleteOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolDeleteOptions != null) {
            clientRequestId = poolDeleteOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolDeleteOptions != null) {
            returnClientRequestId = poolDeleteOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolDeleteOptions != null) {
            ocpDate = poolDeleteOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolDeleteOptions != null) {
            ifMatch = poolDeleteOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolDeleteOptions != null) {
            ifNoneMatch = poolDeleteOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolDeleteOptions != null) {
            ifModifiedSince = poolDeleteOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolDeleteOptions != null) {
            ifUnmodifiedSince = poolDeleteOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.delete(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolDeleteHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolDeleteHeaders> clientResponse = deleteDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolDeleteHeaders> deleteDelegate(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, PoolDeleteHeaders.class);
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @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 boolean object if successful.
     */
    public boolean exists(String poolId) {
        return existsWithServiceResponseAsync(poolId).toBlocking().single().body();
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @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<Boolean> existsAsync(String poolId, final ServiceCallback<Boolean> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(existsWithServiceResponseAsync(poolId), serviceCallback);
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the Boolean object
     */
    public Observable<Boolean> existsAsync(String poolId) {
        return existsWithServiceResponseAsync(poolId).map(new Func1<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>, Boolean>() {
            @Override
            public Boolean call(ServiceResponseWithHeaders<Boolean, PoolExistsHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the Boolean object
     */
    public Observable<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>> existsWithServiceResponseAsync(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 PoolExistsOptions poolExistsOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.exists(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<Void>, Observable<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>> call(Response<Void> response) {
                    try {
                        ServiceResponseWithHeaders<Boolean, PoolExistsHeaders> clientResponse = existsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolExistsOptions 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 boolean object if successful.
     */
    public boolean exists(String poolId, PoolExistsOptions poolExistsOptions) {
        return existsWithServiceResponseAsync(poolId, poolExistsOptions).toBlocking().single().body();
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolExistsOptions 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<Boolean> existsAsync(String poolId, PoolExistsOptions poolExistsOptions, final ServiceCallback<Boolean> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(existsWithServiceResponseAsync(poolId, poolExistsOptions), serviceCallback);
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolExistsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the Boolean object
     */
    public Observable<Boolean> existsAsync(String poolId, PoolExistsOptions poolExistsOptions) {
        return existsWithServiceResponseAsync(poolId, poolExistsOptions).map(new Func1<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>, Boolean>() {
            @Override
            public Boolean call(ServiceResponseWithHeaders<Boolean, PoolExistsHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets basic properties of a Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolExistsOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the Boolean object
     */
    public Observable<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>> existsWithServiceResponseAsync(String poolId, PoolExistsOptions poolExistsOptions) {
        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(poolExistsOptions);
        Integer timeout = null;
        if (poolExistsOptions != null) {
            timeout = poolExistsOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolExistsOptions != null) {
            clientRequestId = poolExistsOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolExistsOptions != null) {
            returnClientRequestId = poolExistsOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolExistsOptions != null) {
            ocpDate = poolExistsOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolExistsOptions != null) {
            ifMatch = poolExistsOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolExistsOptions != null) {
            ifNoneMatch = poolExistsOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolExistsOptions != null) {
            ifModifiedSince = poolExistsOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolExistsOptions != null) {
            ifUnmodifiedSince = poolExistsOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.exists(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<Void>, Observable<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Boolean, PoolExistsHeaders>> call(Response<Void> response) {
                    try {
                        ServiceResponseWithHeaders<Boolean, PoolExistsHeaders> clientResponse = existsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Boolean, PoolExistsHeaders> existsDelegate(Response<Void> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<Boolean, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<Void>() { }.getType())
                .register(404, new TypeToken<Void>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildEmptyWithHeaders(response, PoolExistsHeaders.class);
    }

    /**
     * Gets information about the specified Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @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 CloudPool object if successful.
     */
    public CloudPool get(String poolId) {
        return getWithServiceResponseAsync(poolId).toBlocking().single().body();
    }

    /**
     * Gets information about the specified Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @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<CloudPool> getAsync(String poolId, final ServiceCallback<CloudPool> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getWithServiceResponseAsync(poolId), serviceCallback);
    }

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

    /**
     * Gets information about the specified Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the CloudPool object
     */
    public Observable<ServiceResponseWithHeaders<CloudPool, PoolGetHeaders>> getWithServiceResponseAsync(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 PoolGetOptions poolGetOptions = null;
        String select = null;
        String expand = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.get(poolId, this.client.apiVersion(), this.client.acceptLanguage(), select, expand, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<CloudPool, PoolGetHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<CloudPool, PoolGetHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<CloudPool, PoolGetHeaders> clientResponse = getDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Gets information about the specified Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolGetOptions 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 CloudPool object if successful.
     */
    public CloudPool get(String poolId, PoolGetOptions poolGetOptions) {
        return getWithServiceResponseAsync(poolId, poolGetOptions).toBlocking().single().body();
    }

    /**
     * Gets information about the specified Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolGetOptions 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<CloudPool> getAsync(String poolId, PoolGetOptions poolGetOptions, final ServiceCallback<CloudPool> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getWithServiceResponseAsync(poolId, poolGetOptions), serviceCallback);
    }

    /**
     * Gets information about the specified Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the CloudPool object
     */
    public Observable<CloudPool> getAsync(String poolId, PoolGetOptions poolGetOptions) {
        return getWithServiceResponseAsync(poolId, poolGetOptions).map(new Func1<ServiceResponseWithHeaders<CloudPool, PoolGetHeaders>, CloudPool>() {
            @Override
            public CloudPool call(ServiceResponseWithHeaders<CloudPool, PoolGetHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets information about the specified Pool.
     *
     * @param poolId The ID of the Pool to get.
     * @param poolGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the CloudPool object
     */
    public Observable<ServiceResponseWithHeaders<CloudPool, PoolGetHeaders>> getWithServiceResponseAsync(String poolId, PoolGetOptions poolGetOptions) {
        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(poolGetOptions);
        String select = null;
        if (poolGetOptions != null) {
            select = poolGetOptions.select();
        }
        String expand = null;
        if (poolGetOptions != null) {
            expand = poolGetOptions.expand();
        }
        Integer timeout = null;
        if (poolGetOptions != null) {
            timeout = poolGetOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolGetOptions != null) {
            clientRequestId = poolGetOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolGetOptions != null) {
            returnClientRequestId = poolGetOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolGetOptions != null) {
            ocpDate = poolGetOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolGetOptions != null) {
            ifMatch = poolGetOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolGetOptions != null) {
            ifNoneMatch = poolGetOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolGetOptions != null) {
            ifModifiedSince = poolGetOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolGetOptions != null) {
            ifUnmodifiedSince = poolGetOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.get(poolId, this.client.apiVersion(), this.client.acceptLanguage(), select, expand, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<CloudPool, PoolGetHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<CloudPool, PoolGetHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<CloudPool, PoolGetHeaders> clientResponse = getDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter 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 patch(String poolId, PoolPatchParameter poolPatchParameter) {
        patchWithServiceResponseAsync(poolId, poolPatchParameter).toBlocking().single().body();
    }

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter 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> patchAsync(String poolId, PoolPatchParameter poolPatchParameter, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(patchWithServiceResponseAsync(poolId, poolPatchParameter), serviceCallback);
    }

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> patchAsync(String poolId, PoolPatchParameter poolPatchParameter) {
        return patchWithServiceResponseAsync(poolId, poolPatchParameter).map(new Func1<ServiceResponseWithHeaders<Void, PoolPatchHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolPatchHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolPatchHeaders>> patchWithServiceResponseAsync(String poolId, PoolPatchParameter poolPatchParameter) {
        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 (poolPatchParameter == null) {
            throw new IllegalArgumentException("Parameter poolPatchParameter 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(poolPatchParameter);
        final PoolPatchOptions poolPatchOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.patch(poolId, poolPatchParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolPatchHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolPatchHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolPatchHeaders> clientResponse = patchDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter The parameters for the request.
     * @param poolPatchOptions 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 patch(String poolId, PoolPatchParameter poolPatchParameter, PoolPatchOptions poolPatchOptions) {
        patchWithServiceResponseAsync(poolId, poolPatchParameter, poolPatchOptions).toBlocking().single().body();
    }

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter The parameters for the request.
     * @param poolPatchOptions 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> patchAsync(String poolId, PoolPatchParameter poolPatchParameter, PoolPatchOptions poolPatchOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(patchWithServiceResponseAsync(poolId, poolPatchParameter, poolPatchOptions), serviceCallback);
    }

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter The parameters for the request.
     * @param poolPatchOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> patchAsync(String poolId, PoolPatchParameter poolPatchParameter, PoolPatchOptions poolPatchOptions) {
        return patchWithServiceResponseAsync(poolId, poolPatchParameter, poolPatchOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolPatchHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolPatchHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates the properties of the specified Pool.
     * This only replaces the Pool properties specified in the request. For example, if the Pool has a StartTask associated with it, and a request does not specify a StartTask element, then the Pool keeps the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolPatchParameter The parameters for the request.
     * @param poolPatchOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolPatchHeaders>> patchWithServiceResponseAsync(String poolId, PoolPatchParameter poolPatchParameter, PoolPatchOptions poolPatchOptions) {
        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 (poolPatchParameter == null) {
            throw new IllegalArgumentException("Parameter poolPatchParameter 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(poolPatchParameter);
        Validator.validate(poolPatchOptions);
        Integer timeout = null;
        if (poolPatchOptions != null) {
            timeout = poolPatchOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolPatchOptions != null) {
            clientRequestId = poolPatchOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolPatchOptions != null) {
            returnClientRequestId = poolPatchOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolPatchOptions != null) {
            ocpDate = poolPatchOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolPatchOptions != null) {
            ifMatch = poolPatchOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolPatchOptions != null) {
            ifNoneMatch = poolPatchOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolPatchOptions != null) {
            ifModifiedSince = poolPatchOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolPatchOptions != null) {
            ifUnmodifiedSince = poolPatchOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.patch(poolId, poolPatchParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolPatchHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolPatchHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolPatchHeaders> clientResponse = patchDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolPatchHeaders> patchDelegate(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, PoolPatchHeaders.class);
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @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 disableAutoScale(String poolId) {
        disableAutoScaleWithServiceResponseAsync(poolId).toBlocking().single().body();
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @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> disableAutoScaleAsync(String poolId, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(disableAutoScaleWithServiceResponseAsync(poolId), serviceCallback);
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> disableAutoScaleAsync(String poolId) {
        return disableAutoScaleWithServiceResponseAsync(poolId).map(new Func1<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>> disableAutoScaleWithServiceResponseAsync(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 PoolDisableAutoScaleOptions poolDisableAutoScaleOptions = 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.disableAutoScale(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders> clientResponse = disableAutoScaleDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @param poolDisableAutoScaleOptions 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 disableAutoScale(String poolId, PoolDisableAutoScaleOptions poolDisableAutoScaleOptions) {
        disableAutoScaleWithServiceResponseAsync(poolId, poolDisableAutoScaleOptions).toBlocking().single().body();
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @param poolDisableAutoScaleOptions 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> disableAutoScaleAsync(String poolId, PoolDisableAutoScaleOptions poolDisableAutoScaleOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(disableAutoScaleWithServiceResponseAsync(poolId, poolDisableAutoScaleOptions), serviceCallback);
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @param poolDisableAutoScaleOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> disableAutoScaleAsync(String poolId, PoolDisableAutoScaleOptions poolDisableAutoScaleOptions) {
        return disableAutoScaleWithServiceResponseAsync(poolId, poolDisableAutoScaleOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Disables automatic scaling for a Pool.
     *
     * @param poolId The ID of the Pool on which to disable automatic scaling.
     * @param poolDisableAutoScaleOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>> disableAutoScaleWithServiceResponseAsync(String poolId, PoolDisableAutoScaleOptions poolDisableAutoScaleOptions) {
        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(poolDisableAutoScaleOptions);
        Integer timeout = null;
        if (poolDisableAutoScaleOptions != null) {
            timeout = poolDisableAutoScaleOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolDisableAutoScaleOptions != null) {
            clientRequestId = poolDisableAutoScaleOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolDisableAutoScaleOptions != null) {
            returnClientRequestId = poolDisableAutoScaleOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolDisableAutoScaleOptions != null) {
            ocpDate = poolDisableAutoScaleOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.disableAutoScale(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders> clientResponse = disableAutoScaleDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolDisableAutoScaleHeaders> disableAutoScaleDelegate(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, PoolDisableAutoScaleHeaders.class);
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter 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 enableAutoScale(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter) {
        enableAutoScaleWithServiceResponseAsync(poolId, poolEnableAutoScaleParameter).toBlocking().single().body();
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter 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> enableAutoScaleAsync(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(enableAutoScaleWithServiceResponseAsync(poolId, poolEnableAutoScaleParameter), serviceCallback);
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> enableAutoScaleAsync(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter) {
        return enableAutoScaleWithServiceResponseAsync(poolId, poolEnableAutoScaleParameter).map(new Func1<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>> enableAutoScaleWithServiceResponseAsync(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter) {
        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 (poolEnableAutoScaleParameter == null) {
            throw new IllegalArgumentException("Parameter poolEnableAutoScaleParameter 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(poolEnableAutoScaleParameter);
        final PoolEnableAutoScaleOptions poolEnableAutoScaleOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.enableAutoScale(poolId, poolEnableAutoScaleParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders> clientResponse = enableAutoScaleDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter The parameters for the request.
     * @param poolEnableAutoScaleOptions 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 enableAutoScale(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter, PoolEnableAutoScaleOptions poolEnableAutoScaleOptions) {
        enableAutoScaleWithServiceResponseAsync(poolId, poolEnableAutoScaleParameter, poolEnableAutoScaleOptions).toBlocking().single().body();
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter The parameters for the request.
     * @param poolEnableAutoScaleOptions 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> enableAutoScaleAsync(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter, PoolEnableAutoScaleOptions poolEnableAutoScaleOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(enableAutoScaleWithServiceResponseAsync(poolId, poolEnableAutoScaleParameter, poolEnableAutoScaleOptions), serviceCallback);
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter The parameters for the request.
     * @param poolEnableAutoScaleOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> enableAutoScaleAsync(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter, PoolEnableAutoScaleOptions poolEnableAutoScaleOptions) {
        return enableAutoScaleWithServiceResponseAsync(poolId, poolEnableAutoScaleParameter, poolEnableAutoScaleOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Enables automatic scaling for a Pool.
     * You cannot enable automatic scaling on a Pool if a resize operation is in progress on the Pool. If automatic scaling of the Pool is currently disabled, you must specify a valid autoscale formula as part of the request. If automatic scaling of the Pool is already enabled, you may specify a new autoscale formula and/or a new evaluation interval. You cannot call this API for the same Pool more than once every 30 seconds.
     *
     * @param poolId The ID of the Pool on which to enable automatic scaling.
     * @param poolEnableAutoScaleParameter The parameters for the request.
     * @param poolEnableAutoScaleOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>> enableAutoScaleWithServiceResponseAsync(String poolId, PoolEnableAutoScaleParameter poolEnableAutoScaleParameter, PoolEnableAutoScaleOptions poolEnableAutoScaleOptions) {
        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 (poolEnableAutoScaleParameter == null) {
            throw new IllegalArgumentException("Parameter poolEnableAutoScaleParameter 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(poolEnableAutoScaleParameter);
        Validator.validate(poolEnableAutoScaleOptions);
        Integer timeout = null;
        if (poolEnableAutoScaleOptions != null) {
            timeout = poolEnableAutoScaleOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolEnableAutoScaleOptions != null) {
            clientRequestId = poolEnableAutoScaleOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolEnableAutoScaleOptions != null) {
            returnClientRequestId = poolEnableAutoScaleOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolEnableAutoScaleOptions != null) {
            ocpDate = poolEnableAutoScaleOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolEnableAutoScaleOptions != null) {
            ifMatch = poolEnableAutoScaleOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolEnableAutoScaleOptions != null) {
            ifNoneMatch = poolEnableAutoScaleOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolEnableAutoScaleOptions != null) {
            ifModifiedSince = poolEnableAutoScaleOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolEnableAutoScaleOptions != null) {
            ifUnmodifiedSince = poolEnableAutoScaleOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.enableAutoScale(poolId, poolEnableAutoScaleParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders> clientResponse = enableAutoScaleDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolEnableAutoScaleHeaders> enableAutoScaleDelegate(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, PoolEnableAutoScaleHeaders.class);
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @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 AutoScaleRun object if successful.
     */
    public AutoScaleRun evaluateAutoScale(String poolId, String autoScaleFormula) {
        return evaluateAutoScaleWithServiceResponseAsync(poolId, autoScaleFormula).toBlocking().single().body();
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @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<AutoScaleRun> evaluateAutoScaleAsync(String poolId, String autoScaleFormula, final ServiceCallback<AutoScaleRun> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(evaluateAutoScaleWithServiceResponseAsync(poolId, autoScaleFormula), serviceCallback);
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the AutoScaleRun object
     */
    public Observable<AutoScaleRun> evaluateAutoScaleAsync(String poolId, String autoScaleFormula) {
        return evaluateAutoScaleWithServiceResponseAsync(poolId, autoScaleFormula).map(new Func1<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>, AutoScaleRun>() {
            @Override
            public AutoScaleRun call(ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the AutoScaleRun object
     */
    public Observable<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>> evaluateAutoScaleWithServiceResponseAsync(String poolId, String autoScaleFormula) {
        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.");
        }
        if (autoScaleFormula == null) {
            throw new IllegalArgumentException("Parameter autoScaleFormula is required and cannot be null.");
        }
        final PoolEvaluateAutoScaleOptions poolEvaluateAutoScaleOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        PoolEvaluateAutoScaleParameter poolEvaluateAutoScaleParameter = new PoolEvaluateAutoScaleParameter();
        poolEvaluateAutoScaleParameter.withAutoScaleFormula(autoScaleFormula);
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.evaluateAutoScale(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, poolEvaluateAutoScaleParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders> clientResponse = evaluateAutoScaleDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @param poolEvaluateAutoScaleOptions 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 AutoScaleRun object if successful.
     */
    public AutoScaleRun evaluateAutoScale(String poolId, String autoScaleFormula, PoolEvaluateAutoScaleOptions poolEvaluateAutoScaleOptions) {
        return evaluateAutoScaleWithServiceResponseAsync(poolId, autoScaleFormula, poolEvaluateAutoScaleOptions).toBlocking().single().body();
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @param poolEvaluateAutoScaleOptions 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<AutoScaleRun> evaluateAutoScaleAsync(String poolId, String autoScaleFormula, PoolEvaluateAutoScaleOptions poolEvaluateAutoScaleOptions, final ServiceCallback<AutoScaleRun> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(evaluateAutoScaleWithServiceResponseAsync(poolId, autoScaleFormula, poolEvaluateAutoScaleOptions), serviceCallback);
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @param poolEvaluateAutoScaleOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the AutoScaleRun object
     */
    public Observable<AutoScaleRun> evaluateAutoScaleAsync(String poolId, String autoScaleFormula, PoolEvaluateAutoScaleOptions poolEvaluateAutoScaleOptions) {
        return evaluateAutoScaleWithServiceResponseAsync(poolId, autoScaleFormula, poolEvaluateAutoScaleOptions).map(new Func1<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>, AutoScaleRun>() {
            @Override
            public AutoScaleRun call(ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets the result of evaluating an automatic scaling formula on the Pool.
     * This API is primarily for validating an autoscale formula, as it simply returns the result without applying the formula to the Pool. The Pool must have auto scaling enabled in order to evaluate a formula.
     *
     * @param poolId The ID of the Pool on which to evaluate the automatic scaling formula.
     * @param autoScaleFormula The formula for the desired number of Compute Nodes in the Pool. The formula is validated and its results calculated, but it is not applied to the Pool. To apply the formula to the Pool, 'Enable automatic scaling on a Pool'. For more information about specifying this formula, see Automatically scale Compute Nodes in an Azure Batch Pool (https://azure.microsoft.com/en-us/documentation/articles/batch-automatic-scaling).
     * @param poolEvaluateAutoScaleOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the AutoScaleRun object
     */
    public Observable<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>> evaluateAutoScaleWithServiceResponseAsync(String poolId, String autoScaleFormula, PoolEvaluateAutoScaleOptions poolEvaluateAutoScaleOptions) {
        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.");
        }
        if (autoScaleFormula == null) {
            throw new IllegalArgumentException("Parameter autoScaleFormula is required and cannot be null.");
        }
        Validator.validate(poolEvaluateAutoScaleOptions);
        Integer timeout = null;
        if (poolEvaluateAutoScaleOptions != null) {
            timeout = poolEvaluateAutoScaleOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolEvaluateAutoScaleOptions != null) {
            clientRequestId = poolEvaluateAutoScaleOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolEvaluateAutoScaleOptions != null) {
            returnClientRequestId = poolEvaluateAutoScaleOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolEvaluateAutoScaleOptions != null) {
            ocpDate = poolEvaluateAutoScaleOptions.ocpDate();
        }
        PoolEvaluateAutoScaleParameter poolEvaluateAutoScaleParameter = new PoolEvaluateAutoScaleParameter();
        poolEvaluateAutoScaleParameter.withAutoScaleFormula(autoScaleFormula);
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.evaluateAutoScale(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, poolEvaluateAutoScaleParameter, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<AutoScaleRun, PoolEvaluateAutoScaleHeaders> clientResponse = evaluateAutoScaleDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter 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 resize(String poolId, PoolResizeParameter poolResizeParameter) {
        resizeWithServiceResponseAsync(poolId, poolResizeParameter).toBlocking().single().body();
    }

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter 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> resizeAsync(String poolId, PoolResizeParameter poolResizeParameter, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(resizeWithServiceResponseAsync(poolId, poolResizeParameter), serviceCallback);
    }

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> resizeAsync(String poolId, PoolResizeParameter poolResizeParameter) {
        return resizeWithServiceResponseAsync(poolId, poolResizeParameter).map(new Func1<ServiceResponseWithHeaders<Void, PoolResizeHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolResizeHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolResizeHeaders>> resizeWithServiceResponseAsync(String poolId, PoolResizeParameter poolResizeParameter) {
        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 (poolResizeParameter == null) {
            throw new IllegalArgumentException("Parameter poolResizeParameter 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(poolResizeParameter);
        final PoolResizeOptions poolResizeOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.resize(poolId, poolResizeParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolResizeHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolResizeHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolResizeHeaders> clientResponse = resizeDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter The parameters for the request.
     * @param poolResizeOptions 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 resize(String poolId, PoolResizeParameter poolResizeParameter, PoolResizeOptions poolResizeOptions) {
        resizeWithServiceResponseAsync(poolId, poolResizeParameter, poolResizeOptions).toBlocking().single().body();
    }

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter The parameters for the request.
     * @param poolResizeOptions 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> resizeAsync(String poolId, PoolResizeParameter poolResizeParameter, PoolResizeOptions poolResizeOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(resizeWithServiceResponseAsync(poolId, poolResizeParameter, poolResizeOptions), serviceCallback);
    }

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter The parameters for the request.
     * @param poolResizeOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> resizeAsync(String poolId, PoolResizeParameter poolResizeParameter, PoolResizeOptions poolResizeOptions) {
        return resizeWithServiceResponseAsync(poolId, poolResizeParameter, poolResizeOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolResizeHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolResizeHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Changes the number of Compute Nodes that are assigned to a Pool.
     * You can only resize a Pool when its allocation state is steady. If the Pool is already resizing, the request fails with status code 409. When you resize a Pool, the Pool's allocation state changes from steady to resizing. You cannot resize Pools which are configured for automatic scaling. If you try to do this, the Batch service returns an error 409. If you resize a Pool downwards, the Batch service chooses which Compute Nodes to remove. To remove specific Compute Nodes, use the Pool remove Compute Nodes API instead.
     *
     * @param poolId The ID of the Pool to resize.
     * @param poolResizeParameter The parameters for the request.
     * @param poolResizeOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolResizeHeaders>> resizeWithServiceResponseAsync(String poolId, PoolResizeParameter poolResizeParameter, PoolResizeOptions poolResizeOptions) {
        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 (poolResizeParameter == null) {
            throw new IllegalArgumentException("Parameter poolResizeParameter 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(poolResizeParameter);
        Validator.validate(poolResizeOptions);
        Integer timeout = null;
        if (poolResizeOptions != null) {
            timeout = poolResizeOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolResizeOptions != null) {
            clientRequestId = poolResizeOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolResizeOptions != null) {
            returnClientRequestId = poolResizeOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolResizeOptions != null) {
            ocpDate = poolResizeOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolResizeOptions != null) {
            ifMatch = poolResizeOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolResizeOptions != null) {
            ifNoneMatch = poolResizeOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolResizeOptions != null) {
            ifModifiedSince = poolResizeOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolResizeOptions != null) {
            ifUnmodifiedSince = poolResizeOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.resize(poolId, poolResizeParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolResizeHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolResizeHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolResizeHeaders> clientResponse = resizeDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolResizeHeaders> resizeDelegate(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, PoolResizeHeaders.class);
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @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 stopResize(String poolId) {
        stopResizeWithServiceResponseAsync(poolId).toBlocking().single().body();
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @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> stopResizeAsync(String poolId, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(stopResizeWithServiceResponseAsync(poolId), serviceCallback);
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> stopResizeAsync(String poolId) {
        return stopResizeWithServiceResponseAsync(poolId).map(new Func1<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolStopResizeHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>> stopResizeWithServiceResponseAsync(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 PoolStopResizeOptions poolStopResizeOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.stopResize(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolStopResizeHeaders> clientResponse = stopResizeDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @param poolStopResizeOptions 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 stopResize(String poolId, PoolStopResizeOptions poolStopResizeOptions) {
        stopResizeWithServiceResponseAsync(poolId, poolStopResizeOptions).toBlocking().single().body();
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @param poolStopResizeOptions 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> stopResizeAsync(String poolId, PoolStopResizeOptions poolStopResizeOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(stopResizeWithServiceResponseAsync(poolId, poolStopResizeOptions), serviceCallback);
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @param poolStopResizeOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> stopResizeAsync(String poolId, PoolStopResizeOptions poolStopResizeOptions) {
        return stopResizeWithServiceResponseAsync(poolId, poolStopResizeOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolStopResizeHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Stops an ongoing resize operation on the Pool.
     * This does not restore the Pool to its previous state before the resize operation: it only stops any further changes being made, and the Pool maintains its current state. After stopping, the Pool stabilizes at the number of Compute Nodes it was at when the stop operation was done. During the stop operation, the Pool allocation state changes first to stopping and then to steady. A resize operation need not be an explicit resize Pool request; this API can also be used to halt the initial sizing of the Pool when it is created.
     *
     * @param poolId The ID of the Pool whose resizing you want to stop.
     * @param poolStopResizeOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>> stopResizeWithServiceResponseAsync(String poolId, PoolStopResizeOptions poolStopResizeOptions) {
        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(poolStopResizeOptions);
        Integer timeout = null;
        if (poolStopResizeOptions != null) {
            timeout = poolStopResizeOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolStopResizeOptions != null) {
            clientRequestId = poolStopResizeOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolStopResizeOptions != null) {
            returnClientRequestId = poolStopResizeOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolStopResizeOptions != null) {
            ocpDate = poolStopResizeOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolStopResizeOptions != null) {
            ifMatch = poolStopResizeOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolStopResizeOptions != null) {
            ifNoneMatch = poolStopResizeOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolStopResizeOptions != null) {
            ifModifiedSince = poolStopResizeOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolStopResizeOptions != null) {
            ifUnmodifiedSince = poolStopResizeOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.stopResize(poolId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolStopResizeHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolStopResizeHeaders> clientResponse = stopResizeDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolStopResizeHeaders> stopResizeDelegate(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, PoolStopResizeHeaders.class);
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter 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 updateProperties(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter) {
        updatePropertiesWithServiceResponseAsync(poolId, poolUpdatePropertiesParameter).toBlocking().single().body();
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter 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> updatePropertiesAsync(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(updatePropertiesWithServiceResponseAsync(poolId, poolUpdatePropertiesParameter), serviceCallback);
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> updatePropertiesAsync(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter) {
        return updatePropertiesWithServiceResponseAsync(poolId, poolUpdatePropertiesParameter).map(new Func1<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>> updatePropertiesWithServiceResponseAsync(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter) {
        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 (poolUpdatePropertiesParameter == null) {
            throw new IllegalArgumentException("Parameter poolUpdatePropertiesParameter 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(poolUpdatePropertiesParameter);
        final PoolUpdatePropertiesOptions poolUpdatePropertiesOptions = 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.updateProperties(poolId, poolUpdatePropertiesParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders> clientResponse = updatePropertiesDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter The parameters for the request.
     * @param poolUpdatePropertiesOptions 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 updateProperties(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter, PoolUpdatePropertiesOptions poolUpdatePropertiesOptions) {
        updatePropertiesWithServiceResponseAsync(poolId, poolUpdatePropertiesParameter, poolUpdatePropertiesOptions).toBlocking().single().body();
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter The parameters for the request.
     * @param poolUpdatePropertiesOptions 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> updatePropertiesAsync(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter, PoolUpdatePropertiesOptions poolUpdatePropertiesOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(updatePropertiesWithServiceResponseAsync(poolId, poolUpdatePropertiesParameter, poolUpdatePropertiesOptions), serviceCallback);
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter The parameters for the request.
     * @param poolUpdatePropertiesOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> updatePropertiesAsync(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter, PoolUpdatePropertiesOptions poolUpdatePropertiesOptions) {
        return updatePropertiesWithServiceResponseAsync(poolId, poolUpdatePropertiesParameter, poolUpdatePropertiesOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates the properties of the specified Pool.
     * This fully replaces all the updatable properties of the Pool. For example, if the Pool has a StartTask associated with it and if StartTask is not specified with this request, then the Batch service will remove the existing StartTask.
     *
     * @param poolId The ID of the Pool to update.
     * @param poolUpdatePropertiesParameter The parameters for the request.
     * @param poolUpdatePropertiesOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>> updatePropertiesWithServiceResponseAsync(String poolId, PoolUpdatePropertiesParameter poolUpdatePropertiesParameter, PoolUpdatePropertiesOptions poolUpdatePropertiesOptions) {
        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 (poolUpdatePropertiesParameter == null) {
            throw new IllegalArgumentException("Parameter poolUpdatePropertiesParameter 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(poolUpdatePropertiesParameter);
        Validator.validate(poolUpdatePropertiesOptions);
        Integer timeout = null;
        if (poolUpdatePropertiesOptions != null) {
            timeout = poolUpdatePropertiesOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolUpdatePropertiesOptions != null) {
            clientRequestId = poolUpdatePropertiesOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolUpdatePropertiesOptions != null) {
            returnClientRequestId = poolUpdatePropertiesOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolUpdatePropertiesOptions != null) {
            ocpDate = poolUpdatePropertiesOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.updateProperties(poolId, poolUpdatePropertiesParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolUpdatePropertiesHeaders> clientResponse = updatePropertiesDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter 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 removeNodes(String poolId, NodeRemoveParameter nodeRemoveParameter) {
        removeNodesWithServiceResponseAsync(poolId, nodeRemoveParameter).toBlocking().single().body();
    }

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter 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> removeNodesAsync(String poolId, NodeRemoveParameter nodeRemoveParameter, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(removeNodesWithServiceResponseAsync(poolId, nodeRemoveParameter), serviceCallback);
    }

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> removeNodesAsync(String poolId, NodeRemoveParameter nodeRemoveParameter) {
        return removeNodesWithServiceResponseAsync(poolId, nodeRemoveParameter).map(new Func1<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter The parameters for the request.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>> removeNodesWithServiceResponseAsync(String poolId, NodeRemoveParameter nodeRemoveParameter) {
        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 (nodeRemoveParameter == null) {
            throw new IllegalArgumentException("Parameter nodeRemoveParameter 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(nodeRemoveParameter);
        final PoolRemoveNodesOptions poolRemoveNodesOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String ifMatch = null;
        String ifNoneMatch = null;
        DateTime ifModifiedSince = null;
        DateTime ifUnmodifiedSince = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.removeNodes(poolId, nodeRemoveParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders> clientResponse = removeNodesDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter The parameters for the request.
     * @param poolRemoveNodesOptions 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 removeNodes(String poolId, NodeRemoveParameter nodeRemoveParameter, PoolRemoveNodesOptions poolRemoveNodesOptions) {
        removeNodesWithServiceResponseAsync(poolId, nodeRemoveParameter, poolRemoveNodesOptions).toBlocking().single().body();
    }

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter The parameters for the request.
     * @param poolRemoveNodesOptions 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> removeNodesAsync(String poolId, NodeRemoveParameter nodeRemoveParameter, PoolRemoveNodesOptions poolRemoveNodesOptions, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(removeNodesWithServiceResponseAsync(poolId, nodeRemoveParameter, poolRemoveNodesOptions), serviceCallback);
    }

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter The parameters for the request.
     * @param poolRemoveNodesOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<Void> removeNodesAsync(String poolId, NodeRemoveParameter nodeRemoveParameter, PoolRemoveNodesOptions poolRemoveNodesOptions) {
        return removeNodesWithServiceResponseAsync(poolId, nodeRemoveParameter, poolRemoveNodesOptions).map(new Func1<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>, Void>() {
            @Override
            public Void call(ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Removes Compute Nodes from the specified Pool.
     * This operation can only run when the allocation state of the Pool is steady. When this operation runs, the allocation state changes from steady to resizing. Each request may remove up to 100 nodes.
     *
     * @param poolId The ID of the Pool from which you want to remove Compute Nodes.
     * @param nodeRemoveParameter The parameters for the request.
     * @param poolRemoveNodesOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponseWithHeaders} object if successful.
     */
    public Observable<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>> removeNodesWithServiceResponseAsync(String poolId, NodeRemoveParameter nodeRemoveParameter, PoolRemoveNodesOptions poolRemoveNodesOptions) {
        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 (nodeRemoveParameter == null) {
            throw new IllegalArgumentException("Parameter nodeRemoveParameter 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(nodeRemoveParameter);
        Validator.validate(poolRemoveNodesOptions);
        Integer timeout = null;
        if (poolRemoveNodesOptions != null) {
            timeout = poolRemoveNodesOptions.timeout();
        }
        UUID clientRequestId = null;
        if (poolRemoveNodesOptions != null) {
            clientRequestId = poolRemoveNodesOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolRemoveNodesOptions != null) {
            returnClientRequestId = poolRemoveNodesOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolRemoveNodesOptions != null) {
            ocpDate = poolRemoveNodesOptions.ocpDate();
        }
        String ifMatch = null;
        if (poolRemoveNodesOptions != null) {
            ifMatch = poolRemoveNodesOptions.ifMatch();
        }
        String ifNoneMatch = null;
        if (poolRemoveNodesOptions != null) {
            ifNoneMatch = poolRemoveNodesOptions.ifNoneMatch();
        }
        DateTime ifModifiedSince = null;
        if (poolRemoveNodesOptions != null) {
            ifModifiedSince = poolRemoveNodesOptions.ifModifiedSince();
        }
        DateTime ifUnmodifiedSince = null;
        if (poolRemoveNodesOptions != null) {
            ifUnmodifiedSince = poolRemoveNodesOptions.ifUnmodifiedSince();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        DateTimeRfc1123 ifModifiedSinceConverted = null;
        if (ifModifiedSince != null) {
            ifModifiedSinceConverted = new DateTimeRfc1123(ifModifiedSince);
        }
        DateTimeRfc1123 ifUnmodifiedSinceConverted = null;
        if (ifUnmodifiedSince != null) {
            ifUnmodifiedSinceConverted = new DateTimeRfc1123(ifUnmodifiedSince);
        }
        return service.removeNodes(poolId, nodeRemoveParameter, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, ifMatch, ifNoneMatch, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders> clientResponse = removeNodesDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<Void, PoolRemoveNodesHeaders> removeNodesDelegate(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, PoolRemoveNodesHeaders.class);
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @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;PoolUsageMetrics&gt; object if successful.
     */
    public PagedList<PoolUsageMetrics> listUsageMetricsNext(final String nextPageLink) {
        ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response = listUsageMetricsNextSinglePageAsync(nextPageLink).toBlocking().single();
        return new PagedList<PoolUsageMetrics>(response.body()) {
            @Override
            public Page<PoolUsageMetrics> nextPage(String nextPageLink) {
                return listUsageMetricsNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @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<PoolUsageMetrics>> listUsageMetricsNextAsync(final String nextPageLink, final ServiceFuture<List<PoolUsageMetrics>> serviceFuture, final ListOperationCallback<PoolUsageMetrics> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listUsageMetricsNextSinglePageAsync(nextPageLink),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(String nextPageLink) {
                    return listUsageMetricsNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @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;PoolUsageMetrics&gt; object
     */
    public Observable<Page<PoolUsageMetrics>> listUsageMetricsNextAsync(final String nextPageLink) {
        return listUsageMetricsNextWithServiceResponseAsync(nextPageLink)
            .map(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Page<PoolUsageMetrics>>() {
                @Override
                public Page<PoolUsageMetrics> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @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;PoolUsageMetrics&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsNextWithServiceResponseAsync(final String nextPageLink) {
        return listUsageMetricsNextSinglePageAsync(nextPageLink)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listUsageMetricsNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;PoolUsageMetrics&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsNextSinglePageAsync(final String nextPageLink) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        final PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions = 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.listUsageMetricsNext(nextUrl, this.client.acceptLanguage(), clientRequestId, returnClientRequestId, ocpDateConverted, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<PoolUsageMetrics>, PoolListUsageMetricsHeaders> result = listUsageMetricsNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param poolListUsageMetricsNextOptions 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;PoolUsageMetrics&gt; object if successful.
     */
    public PagedList<PoolUsageMetrics> listUsageMetricsNext(final String nextPageLink, final PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions) {
        ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response = listUsageMetricsNextSinglePageAsync(nextPageLink, poolListUsageMetricsNextOptions).toBlocking().single();
        return new PagedList<PoolUsageMetrics>(response.body()) {
            @Override
            public Page<PoolUsageMetrics> nextPage(String nextPageLink) {
                return listUsageMetricsNextSinglePageAsync(nextPageLink, poolListUsageMetricsNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param poolListUsageMetricsNextOptions 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<PoolUsageMetrics>> listUsageMetricsNextAsync(final String nextPageLink, final PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions, final ServiceFuture<List<PoolUsageMetrics>> serviceFuture, final ListOperationCallback<PoolUsageMetrics> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listUsageMetricsNextSinglePageAsync(nextPageLink, poolListUsageMetricsNextOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(String nextPageLink) {
                    return listUsageMetricsNextSinglePageAsync(nextPageLink, poolListUsageMetricsNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param poolListUsageMetricsNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;PoolUsageMetrics&gt; object
     */
    public Observable<Page<PoolUsageMetrics>> listUsageMetricsNextAsync(final String nextPageLink, final PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions) {
        return listUsageMetricsNextWithServiceResponseAsync(nextPageLink, poolListUsageMetricsNextOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Page<PoolUsageMetrics>>() {
                @Override
                public Page<PoolUsageMetrics> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param poolListUsageMetricsNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;PoolUsageMetrics&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsNextWithServiceResponseAsync(final String nextPageLink, final PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions) {
        return listUsageMetricsNextSinglePageAsync(nextPageLink, poolListUsageMetricsNextOptions)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listUsageMetricsNextWithServiceResponseAsync(nextPageLink, poolListUsageMetricsNextOptions));
                }
            });
    }

    /**
     * Lists the usage metrics, aggregated by Pool across individual time intervals, for the specified Account.
     * If you do not specify a $filter clause including a poolId, the response includes all Pools that existed in the Account in the time range of the returned aggregation intervals. If you do not specify a $filter clause including a startTime or endTime these filters default to the start and end times of the last aggregation interval currently available; that is, only the last aggregation interval is returned.
     *
    ServiceResponseWithHeaders<PageImpl<PoolUsageMetrics>, PoolListUsageMetricsHeaders> * @param nextPageLink The NextLink from the previous successful call to List operation.
    ServiceResponseWithHeaders<PageImpl<PoolUsageMetrics>, PoolListUsageMetricsHeaders> * @param poolListUsageMetricsNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;PoolUsageMetrics&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> listUsageMetricsNextSinglePageAsync(final String nextPageLink, final PoolListUsageMetricsNextOptions poolListUsageMetricsNextOptions) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        Validator.validate(poolListUsageMetricsNextOptions);
        UUID clientRequestId = null;
        if (poolListUsageMetricsNextOptions != null) {
            clientRequestId = poolListUsageMetricsNextOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolListUsageMetricsNextOptions != null) {
            returnClientRequestId = poolListUsageMetricsNextOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolListUsageMetricsNextOptions != null) {
            ocpDate = poolListUsageMetricsNextOptions.ocpDate();
        }
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        String nextUrl = String.format("%s", nextPageLink);
        return service.listUsageMetricsNext(nextUrl, this.client.acceptLanguage(), clientRequestId, returnClientRequestId, ocpDateConverted, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<PoolUsageMetrics>, PoolListUsageMetricsHeaders> result = listUsageMetricsNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<PoolUsageMetrics>, PoolListUsageMetricsHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @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;CloudPool&gt; object if successful.
     */
    public PagedList<CloudPool> listNext(final String nextPageLink) {
        ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response = listNextSinglePageAsync(nextPageLink).toBlocking().single();
        return new PagedList<CloudPool>(response.body()) {
            @Override
            public Page<CloudPool> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @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<CloudPool>> listNextAsync(final String nextPageLink, final ServiceFuture<List<CloudPool>> serviceFuture, final ListOperationCallback<CloudPool> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listNextSinglePageAsync(nextPageLink),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @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;CloudPool&gt; object
     */
    public Observable<Page<CloudPool>> listNextAsync(final String nextPageLink) {
        return listNextWithServiceResponseAsync(nextPageLink)
            .map(new Func1<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>, Page<CloudPool>>() {
                @Override
                public Page<CloudPool> call(ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @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;CloudPool&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> listNextWithServiceResponseAsync(final String nextPageLink) {
        return listNextSinglePageAsync(nextPageLink)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;CloudPool&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> listNextSinglePageAsync(final String nextPageLink) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        final PoolListNextOptions poolListNextOptions = 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<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<CloudPool>, PoolListHeaders> result = listNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param poolListNextOptions 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;CloudPool&gt; object if successful.
     */
    public PagedList<CloudPool> listNext(final String nextPageLink, final PoolListNextOptions poolListNextOptions) {
        ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response = listNextSinglePageAsync(nextPageLink, poolListNextOptions).toBlocking().single();
        return new PagedList<CloudPool>(response.body()) {
            @Override
            public Page<CloudPool> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, poolListNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param poolListNextOptions 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<CloudPool>> listNextAsync(final String nextPageLink, final PoolListNextOptions poolListNextOptions, final ServiceFuture<List<CloudPool>> serviceFuture, final ListOperationCallback<CloudPool> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listNextSinglePageAsync(nextPageLink, poolListNextOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, poolListNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the Pools in the specified Account.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param poolListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;CloudPool&gt; object
     */
    public Observable<Page<CloudPool>> listNextAsync(final String nextPageLink, final PoolListNextOptions poolListNextOptions) {
        return listNextWithServiceResponseAsync(nextPageLink, poolListNextOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>, Page<CloudPool>>() {
                @Override
                public Page<CloudPool> call(ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders> response) {
                    return response.body();
                }
            });
    }

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

    /**
     * Lists all of the Pools in the specified Account.
     *
    ServiceResponseWithHeaders<PageImpl<CloudPool>, PoolListHeaders> * @param nextPageLink The NextLink from the previous successful call to List operation.
    ServiceResponseWithHeaders<PageImpl<CloudPool>, PoolListHeaders> * @param poolListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;CloudPool&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> listNextSinglePageAsync(final String nextPageLink, final PoolListNextOptions poolListNextOptions) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        Validator.validate(poolListNextOptions);
        UUID clientRequestId = null;
        if (poolListNextOptions != null) {
            clientRequestId = poolListNextOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (poolListNextOptions != null) {
            returnClientRequestId = poolListNextOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (poolListNextOptions != null) {
            ocpDate = poolListNextOptions.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<CloudPool>, PoolListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<CloudPool>, PoolListHeaders> result = listNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<CloudPool>, PoolListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

}
