All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.bingads.v13.bulk.BulkOperation Maven / Gradle / Ivy

Go to download

The Bing Ads Java SDK is a library improving developer experience when working with the Bing Ads services by providing high-level access to features such as Bulk API, OAuth Authorization and SOAP API.

There is a newer version: 13.0.22.1
Show newest version
package com.microsoft.bingads.v13.bulk;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.concurrent.Future;

import com.microsoft.bingads.ApiEnvironment;
import com.microsoft.bingads.AsyncCallback;
import com.microsoft.bingads.AuthorizationData;
import com.microsoft.bingads.ServiceClient;
import com.microsoft.bingads.internal.MessageHandler;
import com.microsoft.bingads.internal.ParentCallback;
import com.microsoft.bingads.internal.ResultFuture;
import com.microsoft.bingads.internal.utilities.HttpClientHttpFileService;
import com.microsoft.bingads.internal.utilities.HttpFileService;
import com.microsoft.bingads.internal.utilities.SimpleZipExtractor;
import com.microsoft.bingads.internal.utilities.ZipExtractor;
import com.microsoft.bingads.v13.internal.bulk.BulkOperationStatusProvider;
import com.microsoft.bingads.v13.internal.bulk.BulkOperationTracker;
import com.microsoft.bingads.v13.internal.bulk.Config;
import com.microsoft.bingads.v13.internal.bulk.PollingBulkOperationTracker;

/**
 * Reserved for internal use.
 *
 * The abstract base class that can be derived to represent a bulk operation requested by a user. You can use either the {@link BulkDownloadOperation} or {@link BulkUploadOperation} derived class to poll for the operation status, and then download the results file when available.
 *
 * @param  type of bulk operation status is being tracked
 */
public abstract class BulkOperation {

    /**
     * Represents a user who intends to access the corresponding customer and account.
     */
    private AuthorizationData authorizationData;

    /**
     * The request identifier corresponding to the bulk upload or download, depending on the derived type.
     */
    private String requestId;

    /**
     * The identifier of the log entry that contains the details of the upload or download request.
     */
    private String trackingId;

    /**
     * The amount of time in milliseconds that the upload and download operations should wait before polling the Bulk service for status.
     */   
    private int statusPollIntervalInMilliseconds;
    
    /**
     * The timeout in milliseconds of HttpClient download operation.
     */
    private int downloadHttpTimeoutInMilliseconds;
    
    BulkOperationStatusProvider statusProvider;
    private HttpFileService httpFileService;
    private ZipExtractor zipExtractor;

    private ServiceClient serviceClient;

    private BulkOperationStatus finalStatus;

    BulkOperation(String requestId, AuthorizationData authorizationData) {
        this(requestId, authorizationData, null, null, null);
    }

    BulkOperation(String requestId, AuthorizationData authorizationData, ApiEnvironment apiEnvironment) {
        this(requestId, authorizationData, null, null, apiEnvironment);
    }
    
    BulkOperation(String requestId, AuthorizationData authorizationData, BulkOperationStatusProvider statusProvider) {
        this(requestId, authorizationData, statusProvider, null, null);
    }

    BulkOperation(String requestId, AuthorizationData authorizationData, BulkOperationStatusProvider statusProvider, String trackingId) {
    	 this(requestId, authorizationData, statusProvider, trackingId, null);
    }
    
    BulkOperation(String requestId, AuthorizationData authorizationData, BulkOperationStatusProvider statusProvider, String trackingId, ApiEnvironment apiEnvironment) {
        this.statusProvider = statusProvider;
        this.requestId = requestId;
        this.authorizationData = authorizationData;
        this.trackingId = trackingId;

        statusPollIntervalInMilliseconds = Config.DEFAULT_STATUS_CHECK_INTERVAL_IN_MS;
        
        downloadHttpTimeoutInMilliseconds = Config.DEFAULT_HTTPCLIENT_TIMEOUT_IN_MS;

        this.serviceClient = new ServiceClient(authorizationData, apiEnvironment, IBulkService.class);

        zipExtractor = new SimpleZipExtractor();

        httpFileService = new HttpClientHttpFileService();
    }

    /**
     * Runs asynchronously until the bulk service has finished processing the bulk operation.
     *
     * @param callback A handler that will be called with the BulkOperation when it has completed
     *
     * @return a Future that will be completed when the result file is available
     */
    public Future> trackAsync(AsyncCallback> callback) {
        return trackAsync(null, callback);
    }

    /**
     * Runs asynchronously until the bulk service has finished processing the bulk operation.
     *
     * @param progress An object to be updated with the progress of the operation
     * @param callback A handler that will be called with the BulkOperation when it has completed
     *
     * @return a Future that will be completed when the result file is available
     */
    public Future> trackAsync(Progress progress, AsyncCallback> callback) {
        BulkOperationTracker tracker = generateTracker(progress);

        final ResultFuture> resultFuture = new ResultFuture>(callback);

        tracker.trackResultFileAsync(new ParentCallback>(resultFuture) {
            @Override
            public void onSuccess(BulkOperationStatus status) {
                finalStatus = status;

                resultFuture.setResult(finalStatus);
            }
        });

        return resultFuture;
    }

    private BulkOperationTracker generateTracker(Progress progress) {
        BulkOperationTracker tracker;

        tracker = new PollingBulkOperationTracker(statusProvider, this.serviceClient, progress, this.statusPollIntervalInMilliseconds);

        return tracker;
    }

    /**
     * Gets the status of the bulk operation.
     *
     * @return the current status of the bulk operation
     */
    public Future> getStatusAsync(AsyncCallback> callback) {
        final ResultFuture> resultFuture = new ResultFuture>(callback);

        if (finalStatus != null) {
            resultFuture.setResult(this.finalStatus);

            return resultFuture;
        }
        
       
        statusProvider.getCurrentStatus(this.serviceClient, new ParentCallback>(resultFuture) {
            @Override
            
            public void onSuccess(BulkOperationStatus currentStatus) {
            	
                if (statusProvider.isFinalStatus(currentStatus)) {
                    finalStatus = currentStatus;
                }

                resultFuture.setResult(currentStatus);
            }
        });

        return resultFuture;
    }

    public AuthorizationData getAuthorizationData() {
        return authorizationData;
    }

    public String getRequestId() {
        return requestId;
    }

    public String getTrackingId() {
        return trackingId;
    }

    BulkOperationStatusProvider getStatusProvider() {
        return statusProvider;
    }

    void setRequestId(String requestId) {
        this.requestId = requestId;
    }

    void setTrackingId(String trackingId) {
        this.trackingId = trackingId;
    }

    void setStatusProvider(BulkOperationStatusProvider statusProvider) {
        this.statusProvider = statusProvider;
    }

    HttpFileService getHttpFileService() {
        return httpFileService;
    }

    void setHttpFileService(HttpFileService httpFileService) {
        this.httpFileService = httpFileService;
    }

    ZipExtractor getZipExtractor() {
        return zipExtractor;
    }

    void setZipExtractor(ZipExtractor zipExtractor) {
        this.zipExtractor = zipExtractor;
    }

    /**
     * Gets the time interval in milliseconds between two status polling attempts. The default value is 5000 (5 second).
     */
    public int getStatusPollIntervalInMilliseconds() {
        return statusPollIntervalInMilliseconds;
    }

    /**
     * Sets the time interval in milliseconds between two status polling attempts. The default value is 5000 (5 second).
     */
    public void setStatusPollIntervalInMilliseconds(int statusPollIntervalInMilliseconds) {
        this.statusPollIntervalInMilliseconds = statusPollIntervalInMilliseconds;
    }

    /**
     * Gets the timeout of HttpClient download operation. The default value is 100000(100s).
     */
	public int getDownloadHttpTimeoutInMilliseconds() {
		return downloadHttpTimeoutInMilliseconds;
	}

	/**
     * Sets the timeout of HttpClient download operation. The default value is 100000(100s).
     */
	public void setDownloadHttpTimeoutInMilliseconds(int downloadHttpTimeoutInMilliseconds) {
		this.downloadHttpTimeoutInMilliseconds = downloadHttpTimeoutInMilliseconds;
	}

	/**
     * Downloads and optionally decompress the result file from the bulk operation
     * @param localResultDirectoryName the directory to place the result file in
     * @param localResultFileName the name to use for final result file
     * @param decompress indicates whether the result file should be unzipped
     * @param callback {@link AsyncCallback} object with {@link File}
     *
     * @return a {@link File} object pointing to the result file wrapped in Future
     *
     * @throws IOException
     * @throws URISyntaxException
     */
    public Future downloadResultFileAsync(File localResultDirectoryName, String localResultFileName, boolean decompress, AsyncCallback callback) throws IOException, URISyntaxException {
        return downloadResultFileAsync(localResultDirectoryName, localResultFileName, decompress, false, callback);
    }

    /**
     * Downloads and optionally decompress the result file from the bulk operation, allows to overwrite the local result file.
     *
     * @param localResultDirectoryName the directory to place the result file in
     * @param localResultFileName the name to use for final result file
     * @param decompress indicates whether the result file should be unzipped
     * @param overwrite indicates whether can overwrite if target file exists
     * @param callback {@link AsyncCallback} object with {@link File}
     *
     * @return a {@link File} object pointing to the result file wrapped in Future
     */
    public Future downloadResultFileAsync(File localResultDirectoryName, String localResultFileName, boolean decompress, boolean overwrite, AsyncCallback callback) throws IOException, URISyntaxException {
        return downloadResultFileAsyncImpl(localResultDirectoryName, localResultFileName, decompress, overwrite, callback);
    }

    abstract RuntimeException getOperationCouldNotBeCompletedException(List errors, TStatus status);

    private Future downloadResultFileAsyncImpl(final File localResultDirectoryName, final String localResultFileName, final boolean decompress, final boolean overwrite, AsyncCallback callback) throws IOException, URISyntaxException {
        final ResultFuture resultFuture = new ResultFuture(callback);

        if (finalStatus == null) {
            getStatusAsync(new ParentCallback>(resultFuture) {
                @Override
                public void onSuccess(BulkOperationStatus result) throws IOException, URISyntaxException {
                    if (finalStatus == null) {
                        resultFuture.setException(new BulkOperationInProgressException());

                        return;
                    }

                    File resultFile = downloadFileWithFinalStatus(localResultDirectoryName, localResultFileName, decompress, overwrite);

                    resultFuture.setResult(resultFile);
                }
            });
        } else {
            File resultFile = downloadFileWithFinalStatus(localResultDirectoryName, localResultFileName, decompress, overwrite);

            resultFuture.setResult(resultFile);
        }

        return resultFuture;
    }

    private File downloadFileWithFinalStatus(File localResultDirectoryName, String localResultFileName, final boolean decompress, final boolean overwrite) throws IOException, URISyntaxException {
        if (!statusProvider.isSuccessStatus(finalStatus.getStatus())) {
            List errors = finalStatus.getErrors();

            throw getOperationCouldNotBeCompletedException(errors, finalStatus.getStatus());
        }

        String effectiveFileName;

        if (localResultFileName == null) {
            effectiveFileName = requestId;
        } else {
            effectiveFileName = localResultFileName;
        }

        final File fullPath = new File(localResultDirectoryName, effectiveFileName);

        final File zipResultPath = new File(localResultDirectoryName, effectiveFileName + ".zip");

        downloadResultFileZip(finalStatus.getResultFileUrl(), zipResultPath, overwrite);

        if (!decompress) {
            return zipResultPath;
        }
        
        File extractedFile = zipExtractor.extractFirstEntryToFile(zipResultPath, fullPath, localResultFileName == null, overwrite);
        
        zipResultPath.delete();
        
        MessageHandler.getInstance().handleDirectMessage("Bulk Download... RequestId: " + requestId + "; DownloadUrl: " + finalStatus.getResultFileUrl() + "; LocalPath: " + localResultDirectoryName.getPath());

        return extractedFile;
    }

    private File downloadResultFileZip(String url, File tempZipFile, boolean overwrite) throws IOException, URISyntaxException {
        if (httpFileService == null) {
            httpFileService = new HttpClientHttpFileService();
        }

        httpFileService.downloadFile(url, tempZipFile, overwrite, downloadHttpTimeoutInMilliseconds);

        return tempZipFile;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy