io.proximax.download.Downloader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-chain-xipfs-sdk Show documentation
Show all versions of java-chain-xipfs-sdk Show documentation
Official ProximaX P2P Storage SDK Library in Java.
The newest version!
package io.proximax.download;
import io.proximax.sdk.model.transaction.TransferTransaction;
import io.proximax.async.AsyncCallbacks;
import io.proximax.async.AsyncTask;
import io.proximax.connection.ConnectionConfig;
import io.proximax.exceptions.DirectDownloadFailureException;
import io.proximax.exceptions.DownloadFailureException;
import io.proximax.exceptions.DownloadInitFailureException;
import io.proximax.model.ProximaxDataModel;
import io.proximax.model.ProximaxMessagePayloadModel;
import io.proximax.privacy.strategy.PrivacyStrategy;
import io.proximax.service.BlockchainTransactionService;
import io.proximax.service.RetrieveProximaxDataService;
import io.proximax.service.RetrieveProximaxMessagePayloadService;
import io.proximax.utils.AsyncUtils;
import io.reactivex.Observable;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Optional;
import java.util.function.Supplier;
import static io.proximax.utils.ParameterValidationUtils.checkParameter;
/**
* The Downloader class that handles the download functionality
*
*
* The Downloader creation requires a ConnectionConfig that defines generally where the download will be done.
* The instance of the class can be reused to download multiple times.
*
*
* Downloads can be done by providing the blockchain transaction hash or the data hash.
* A complete download can be done to get the data and its accompanying details,
* and a direct download can be done to retrieve the data only.
*
* @see ConnectionConfig
* @see DownloadParameter
* @see DirectDownloadParameter
*/
public class Downloader {
private final BlockchainTransactionService blockchainTransactionService;
private final RetrieveProximaxMessagePayloadService retrieveProximaxMessagePayloadService;
private final RetrieveProximaxDataService retrieveProximaxDataService;
/**
* Construct the class with a ConnectionConfig
*
* @param connectionConfig the connection config that defines generally where the download will be sent
*/
public Downloader(ConnectionConfig connectionConfig) {
this.retrieveProximaxDataService = new RetrieveProximaxDataService(connectionConfig.getFileStorageConnection());
try {
this.retrieveProximaxMessagePayloadService = new RetrieveProximaxMessagePayloadService(connectionConfig.getBlockchainNetworkConnection());
this.blockchainTransactionService = new BlockchainTransactionService(connectionConfig.getBlockchainNetworkConnection());
} catch (MalformedURLException e) {
throw new DownloadInitFailureException("Failed to initialize", e);
}
}
Downloader(BlockchainTransactionService blockchainTransactionService,
RetrieveProximaxMessagePayloadService retrieveProximaxMessagePayloadService,
RetrieveProximaxDataService retrieveProximaxDataService) {
this.blockchainTransactionService = blockchainTransactionService;
this.retrieveProximaxMessagePayloadService = retrieveProximaxMessagePayloadService;
this.retrieveProximaxDataService = retrieveProximaxDataService;
}
/**
* Retrieve synchronously the data and its accompanying details.
* This would use the blockchain transaction hash to retrieve the data's byte stream and its details.
*
*
* @param downloadParam the download parameter
* @return the download result
*/
public DownloadResult download(final DownloadParameter downloadParam) {
checkParameter(downloadParam != null, "downloadParam is required");
return doCompleteDownload(downloadParam).blockingFirst();
}
/**
* Retrieve asynchronously the data and its accompanying details.
* This would use the blockchain transaction hash to retrieve the data's byte stream and its details.
*
*
* @param downloadParam the download parameter
* @param asyncCallbacks an optional callbacks when succeeded or failed
* @return the download result containing the list of data
*/
public AsyncTask downloadAsync(DownloadParameter downloadParam, AsyncCallbacks asyncCallbacks) {
checkParameter(downloadParam != null, "downloadParam is required");
final AsyncTask asyncTask = new AsyncTask();
AsyncUtils.processFirstItem(this.doCompleteDownload(downloadParam), asyncCallbacks, asyncTask);
return asyncTask;
}
/**
* Retrieve synchronously the data
*
* @param directDownloadParameter the direct download data parameter
* @return the data
*/
public InputStream directDownload(final DirectDownloadParameter directDownloadParameter) {
checkParameter(directDownloadParameter != null, "directDownloadParameter is required");
return doDirectDownload(directDownloadParameter).blockingFirst();
}
/**
* Retrieve asynchronously the data
*
* @param directDownloadParameter the direct download data parameter
* @param asyncCallbacks an optional callbacks when succeeded or failed
* @return the data
*/
public AsyncTask directDownloadAsync(DirectDownloadParameter directDownloadParameter, AsyncCallbacks asyncCallbacks) {
checkParameter(directDownloadParameter != null, "directDownloadParameter is required");
final AsyncTask asyncTask = new AsyncTask();
AsyncUtils.processFirstItem(this.doDirectDownload(directDownloadParameter), asyncCallbacks, asyncTask);
return asyncTask;
}
private Observable doCompleteDownload(DownloadParameter downloadParam) {
return Observable.fromCallable(
() -> {
try {
final DownloadResult downloadResult = blockchainTransactionService.getTransferTransaction(downloadParam.getTransactionHash())
.map(transferTransaction -> retrieveProximaxMessagePayloadService.getMessagePayload(transferTransaction,
downloadParam.getAccountPrivateKey()))
.map(messagePayload -> createCompleteDownloadResult(messagePayload,
() -> getDataByteStream(Optional.of(messagePayload), null, downloadParam.getPrivacyStrategy(),
downloadParam.getValidateDigest(), null).blockingFirst(),
downloadParam.getTransactionHash())).blockingFirst();
return downloadResult;
} catch (RuntimeException ex) {
throw new DownloadFailureException("Download failed.", ex);
}
}
);
}
private DownloadResult createCompleteDownloadResult(ProximaxMessagePayloadModel messagePayload,
Supplier byteStreamSupplier, String transactionHash) {
final ProximaxDataModel data = messagePayload.getData();
return DownloadResult.create(transactionHash, messagePayload.getPrivacyType(), messagePayload.getVersion(),
new DownloadResultData(byteStreamSupplier, data.getDigest(), data.getDataHash(), data.getTimestamp(),
data.getDescription(), data.getName(), data.getContentType(), data.getMetadata()));
}
private Observable doDirectDownload(DirectDownloadParameter downloadParam) {
return Observable.fromCallable(
() -> {
try {
final InputStream inputStream = getOptionalBlockchainTransaction(downloadParam.getTransactionHash())
.map(transferTransactionOpt -> transferTransactionOpt.map(transferTransaction ->
retrieveProximaxMessagePayloadService.getMessagePayload(transferTransaction, downloadParam.getAccountPrivateKey())))
.flatMap(messagePayload -> getDataByteStream(messagePayload, downloadParam.getDataHash(), downloadParam.getPrivacyStrategy(),
downloadParam.getValidateDigest(), downloadParam.getDigest())).blockingFirst();
return inputStream;
} catch (RuntimeException ex) {
throw new DirectDownloadFailureException("Direct download failed.", ex);
}
}
);
}
private Observable> getOptionalBlockchainTransaction(String transactionHash) {
return Optional.ofNullable(transactionHash)
.map(hash -> blockchainTransactionService.getTransferTransaction(hash).map(Optional::of))
.orElse(Observable.just(Optional.empty()));
}
private Observable getDataByteStream(Optional messagePayload, String dataHash, PrivacyStrategy privacyStrategy,
boolean validateDigest, String digest) {
final String resolvedDataHash = messagePayload.map(payload -> payload.getData().getDataHash()).orElse(dataHash);
final String resolvedDigest = messagePayload.map(payload -> payload.getData().getDigest()).orElse(digest);
final String resolvedContentType = messagePayload.map(payload -> payload.getData().getContentType()).orElse(null);
return retrieveProximaxDataService.getDataByteStream(resolvedDataHash, privacyStrategy, validateDigest, resolvedDigest, resolvedContentType);
}
}