Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Generated by delombok at Thu Oct 10 18:56:32 UTC 2024
/* SPDX-License-Identifier: Apache-2.0
Copyright 2023 Atlan Pte. Ltd. */
package com.atlan.util;
import com.atlan.AtlanClient;
import com.atlan.exception.AtlanException;
import com.atlan.model.assets.Asset;
import com.atlan.model.core.AssetMutationResponse;
import com.atlan.model.enums.AssetCreationHandling;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Utility class for managing bulk updates across multiple parallel-running batches.
*/
public class ParallelBatch {
/**
* Connectivity to an Atlan tenant.
*/
private AtlanClient client;
/**
* Maximum number of assets to submit in each batch.
*/
private int maxSize;
/**
* Whether to replace Atlan tags (true), or ignore them (false).
*/
private boolean replaceAtlanTags;
/**
* How to handle any custom metadata on assets (ignore, replace, or merge).
*/
private AssetBatch.CustomMetadataHandling customMetadataHandling;
/**
* Whether to capture details about any failures (true) or throw exceptions for any failures (false).
*/
private boolean captureFailures;
/**
* Whether to track the basic information about every asset that is created or updated (true) or only track counts (false).
*/
private boolean track;
/**
* Whether to allow assets to be created (false) or only allow existing assets to be updated (true).
*/
private boolean updateOnly;
/**
* When running with {@link #updateOnly} as true, whether to consider only exact matches (false) or ignore case (true).
*/
private boolean caseSensitive;
/**
* When allowing assets to be created, how to handle those creations (full assets or partial assets).
*/
private AssetCreationHandling creationHandling;
/**
* Whether tables and views should be treated interchangeably (an asset in the batch marked as a table will attempt to match a view if not found as a table, and vice versa).
*/
private boolean tableViewAgnostic;
private final Map batchMap = new ConcurrentHashMap<>();
private final List created = new ArrayList<>();
private final List updated = new ArrayList<>();
private final List restored = new ArrayList<>();
private final List failures = new ArrayList<>();
private final List skipped = new ArrayList<>();
private final Map resolvedGuids = new HashMap<>();
private final Map resolvedQualifiedNames = new HashMap<>();
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
*/
public ParallelBatch(AtlanClient client, int maxSize) {
this(client, maxSize, false, AssetBatch.CustomMetadataHandling.IGNORE);
}
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
* @param replaceAtlanTags if true, all Atlan tags on an existing asset will be overwritten; if false, all Atlan tags will be ignored
* @param customMetadataHandling how to handle custom metadata (ignore it, replace it (wiping out anything pre-existing), or merge it)
*/
public ParallelBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, AssetBatch.CustomMetadataHandling customMetadataHandling) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, false);
}
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
* @param replaceAtlanTags if true, all Atlan tags on an existing asset will be overwritten; if false, all Atlan tags will be ignored
* @param customMetadataHandling how to handle custom metadata (ignore it, replace it (wiping out anything pre-existing), or merge it)
* @param captureFailures when true, any failed batches will be captured and retained rather than exceptions being raised (for large amounts of processing this could cause memory issues!)
*/
public ParallelBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, AssetBatch.CustomMetadataHandling customMetadataHandling, boolean captureFailures) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, false);
}
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
* @param replaceAtlanTags if true, all Atlan tags on an existing asset will be overwritten; if false, all Atlan tags will be ignored
* @param customMetadataHandling how to handle custom metadata (ignore it, replace it (wiping out anything pre-existing), or merge it)
* @param captureFailures when true, any failed batches will be captured and retained rather than exceptions being raised (for large amounts of processing this could cause memory issues!)
* @param updateOnly when true, only attempt to update existing assets and do not create any assets (note: this will incur a performance penalty)
*/
public ParallelBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, AssetBatch.CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, true);
}
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
* @param replaceAtlanTags if true, all Atlan tags on an existing asset will be overwritten; if false, all Atlan tags will be ignored
* @param customMetadataHandling how to handle custom metadata (ignore it, replace it (wiping out anything pre-existing), or merge it)
* @param captureFailures when true, any failed batches will be captured and retained rather than exceptions being raised (for large amounts of processing this could cause memory issues!)
* @param updateOnly when true, only attempt to update existing assets and do not create any assets (note: this will incur a performance penalty)
* @param track when false, details about each created and updated asset will no longer be tracked (only an overall count of each) -- useful if you intend to send close to (or more than) 1 million assets through a batch
*/
public ParallelBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, AssetBatch.CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, track, true);
}
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
* @param replaceAtlanTags if true, all Atlan tags on an existing asset will be overwritten; if false, all Atlan tags will be ignored
* @param customMetadataHandling how to handle custom metadata (ignore it, replace it (wiping out anything pre-existing), or merge it)
* @param captureFailures when true, any failed batches will be captured and retained rather than exceptions being raised (for large amounts of processing this could cause memory issues!)
* @param updateOnly when true, only attempt to update existing assets and do not create any assets (note: this will incur a performance penalty)
* @param track when false, details about each created and updated asset will no longer be tracked (only an overall count of each) -- useful if you intend to send close to (or more than) 1 million assets through a batch
* @param caseSensitive (only applies when updateOnly is true) attempt to match assets case-sensitively (true) or case-insensitively (false)
*/
public ParallelBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, AssetBatch.CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track, boolean caseSensitive) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, track, caseSensitive, AssetCreationHandling.FULL);
}
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
* @param replaceAtlanTags if true, all Atlan tags on an existing asset will be overwritten; if false, all Atlan tags will be ignored
* @param customMetadataHandling how to handle custom metadata (ignore it, replace it (wiping out anything pre-existing), or merge it)
* @param captureFailures when true, any failed batches will be captured and retained rather than exceptions being raised (for large amounts of processing this could cause memory issues!)
* @param updateOnly when true, only attempt to update existing assets and do not create any assets (note: this will incur a performance penalty)
* @param track when false, details about each created and updated asset will no longer be tracked (only an overall count of each) -- useful if you intend to send close to (or more than) 1 million assets through a batch
* @param caseSensitive (only applies when updateOnly is true) attempt to match assets case-sensitively (true) or case-insensitively (false)
* @param creationHandling if assets are to be created, how they should be created (as full assets or only partial assets)
*/
public ParallelBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, AssetBatch.CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track, boolean caseSensitive, AssetCreationHandling creationHandling) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, track, caseSensitive, creationHandling, false);
}
/**
* Create a new batch of assets to be bulk-saved, in parallel (across threads).
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
* @param replaceAtlanTags if true, all Atlan tags on an existing asset will be overwritten; if false, all Atlan tags will be ignored
* @param customMetadataHandling how to handle custom metadata (ignore it, replace it (wiping out anything pre-existing), or merge it)
* @param captureFailures when true, any failed batches will be captured and retained rather than exceptions being raised (for large amounts of processing this could cause memory issues!)
* @param updateOnly when true, only attempt to update existing assets and do not create any assets (note: this will incur a performance penalty)
* @param track when false, details about each created and updated asset will no longer be tracked (only an overall count of each) -- useful if you intend to send close to (or more than) 1 million assets through a batch
* @param caseSensitive (only applies when updateOnly is true) attempt to match assets case-sensitively (true) or case-insensitively (false)
* @param creationHandling if assets are to be created, how they should be created (as full assets or only partial assets)
* @param tableViewAgnostic if true, tables and views will be treated interchangeably (an asset in the batch marked as a table will attempt to match a view if not found as a table, and vice versa)
*/
public ParallelBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, AssetBatch.CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track, boolean caseSensitive, AssetCreationHandling creationHandling, boolean tableViewAgnostic) {
this.client = client;
this.maxSize = maxSize;
this.replaceAtlanTags = replaceAtlanTags;
this.customMetadataHandling = customMetadataHandling;
this.captureFailures = captureFailures;
this.track = track;
this.updateOnly = updateOnly;
this.caseSensitive = caseSensitive;
this.creationHandling = creationHandling;
this.tableViewAgnostic = tableViewAgnostic;
}
/**
* Add an asset to the batch to be processed.
*
* @param single the asset to add to a batch
* @return the assets that were created or updated in this batch, or null if the batch is still queued
* @throws AtlanException on any problems adding the asset to or processing the batch
*/
public AssetMutationResponse add(Asset single) throws AtlanException {
long id = Thread.currentThread().getId();
if (!batchMap.containsKey(id)) {
batchMap.put(id, new AssetBatch(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, track, !caseSensitive, creationHandling, tableViewAgnostic));
}
return batchMap.get(id).add(single);
}
/**
* Flush any remaining assets in the parallel batches.
*
* @throws IllegalStateException on any problems flushing (submitting) any of the parallel batches
*/
public void flush() throws AtlanException {
batchMap.values().parallelStream().forEach(batch -> {
try {
batch.flush();
} catch (AtlanException e) {
throw new IllegalStateException(e);
}
});
}
/**
* Number of assets that were created (no details, only a count).
*
* @return a count of the number of created assets, across all parallel batches
*/
public long getNumCreated() {
long count = 0;
for (AssetBatch batch : batchMap.values()) {
count += batch.getNumCreated().get();
}
return count;
}
/**
* Number of assets that were updated (no details, only a count).
*
* @return a count of the number of updated assets, across all parallel batches
*/
public long getNumUpdated() {
long count = 0;
for (AssetBatch batch : batchMap.values()) {
count += batch.getNumUpdated().get();
}
return count;
}
/**
* Number of assets that were potentially restored from being archived, or otherwise touched
* without actually being updated (no details, just a count).
*
* @return a count of the number of potentially restored assets, across all parallel batches
*/
public long getNumRestored() {
long count = 0;
for (AssetBatch batch : batchMap.values()) {
count += batch.getNumRestored().get();
}
return count;
}
/**
* Assets that were created (minimal info only).
*
* @return all created assets, across all parallel batches
*/
public List getCreated() {
if (!track) {
return null;
}
if (created.isEmpty()) {
for (AssetBatch batch : batchMap.values()) {
created.addAll(batch.getCreated());
}
}
return created;
}
/**
* Assets that were updated (minimal info only).
*
* @return all updated assets, across all parallel batches
*/
public List getUpdated() {
if (!track) {
return null;
}
if (updated.isEmpty()) {
for (AssetBatch batch : batchMap.values()) {
updated.addAll(batch.getUpdated());
}
}
return updated;
}
/**
* Assets that were potentially restored from being archived, or otherwise touched without actually
* being updated (minimal info only).
*
* @return all potentially restored assets, across all parallel batches
*/
public List getRestored() {
if (!track) {
return null;
}
if (restored.isEmpty()) {
for (AssetBatch batch : batchMap.values()) {
restored.addAll(batch.getRestored());
}
}
return restored;
}
/**
* Batches that failed to be committed (only populated when captureFailures is set to true).
*
* @return all batches that failed, across all parallel batches
*/
public List getFailures() {
if (failures.isEmpty()) {
for (AssetBatch batch : batchMap.values()) {
failures.addAll(batch.getFailures());
}
}
return failures;
}
/**
* Assets that were skipped, when updateOnly is requested and the asset does not exist in Atlan.
*
* @return all assets that were skipped, across all parallel batches
*/
public List getSkipped() {
if (skipped.isEmpty()) {
for (AssetBatch batch : batchMap.values()) {
skipped.addAll(batch.getSkipped());
}
}
return skipped;
}
/**
* Map from placeholder GUID to resolved (actual) GUID, for all assets that were processed through the batch.
*
* @return all resolved GUIDs, across all parallel batches
*/
public Map getResolvedGuids() {
if (resolvedGuids.isEmpty()) {
for (AssetBatch batch : batchMap.values()) {
resolvedGuids.putAll(batch.getResolvedGuids());
}
}
return resolvedGuids;
}
/**
* Map from case-insensitive qualifiedName to resolved (actual) qualifiedName,
* for all assets that were processed through the batch.
* Note: this is only populated when caseSensitive is false, and will otherwise be empty
*
* @return all resolved qualifiedNames, across all parallel batches
*/
public Map getResolvedQualifiedNames() {
if (resolvedQualifiedNames.isEmpty()) {
for (AssetBatch batch : batchMap.values()) {
resolvedQualifiedNames.putAll(batch.getResolvedQualifiedNames());
}
}
return resolvedQualifiedNames;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static int $default$maxSize() {
return 20;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static boolean $default$replaceAtlanTags() {
return false;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static AssetBatch.CustomMetadataHandling $default$customMetadataHandling() {
return AssetBatch.CustomMetadataHandling.IGNORE;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static boolean $default$captureFailures() {
return false;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static boolean $default$track() {
return true;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static boolean $default$updateOnly() {
return false;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static boolean $default$caseSensitive() {
return true;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static AssetCreationHandling $default$creationHandling() {
return AssetCreationHandling.FULL;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static boolean $default$tableViewAgnostic() {
return false;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public static class ParallelBatchBuilder {
@java.lang.SuppressWarnings("all")
@lombok.Generated
private AtlanClient client;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean maxSize$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private int maxSize$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean replaceAtlanTags$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean replaceAtlanTags$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean customMetadataHandling$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private AssetBatch.CustomMetadataHandling customMetadataHandling$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean captureFailures$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean captureFailures$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean track$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean track$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean updateOnly$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean updateOnly$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean caseSensitive$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean caseSensitive$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean creationHandling$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private AssetCreationHandling creationHandling$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean tableViewAgnostic$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean tableViewAgnostic$value;
@java.lang.SuppressWarnings("all")
@lombok.Generated
ParallelBatchBuilder() {
}
/**
* Connectivity to an Atlan tenant.
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder client(final AtlanClient client) {
this.client = client;
return this;
}
/**
* Maximum number of assets to submit in each batch.
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder maxSize(final int maxSize) {
this.maxSize$value = maxSize;
maxSize$set = true;
return this;
}
/**
* Whether to replace Atlan tags (true), or ignore them (false).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder replaceAtlanTags(final boolean replaceAtlanTags) {
this.replaceAtlanTags$value = replaceAtlanTags;
replaceAtlanTags$set = true;
return this;
}
/**
* How to handle any custom metadata on assets (ignore, replace, or merge).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder customMetadataHandling(final AssetBatch.CustomMetadataHandling customMetadataHandling) {
this.customMetadataHandling$value = customMetadataHandling;
customMetadataHandling$set = true;
return this;
}
/**
* Whether to capture details about any failures (true) or throw exceptions for any failures (false).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder captureFailures(final boolean captureFailures) {
this.captureFailures$value = captureFailures;
captureFailures$set = true;
return this;
}
/**
* Whether to track the basic information about every asset that is created or updated (true) or only track counts (false).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder track(final boolean track) {
this.track$value = track;
track$set = true;
return this;
}
/**
* Whether to allow assets to be created (false) or only allow existing assets to be updated (true).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder updateOnly(final boolean updateOnly) {
this.updateOnly$value = updateOnly;
updateOnly$set = true;
return this;
}
/**
* When running with {@link #updateOnly} as true, whether to consider only exact matches (false) or ignore case (true).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder caseSensitive(final boolean caseSensitive) {
this.caseSensitive$value = caseSensitive;
caseSensitive$set = true;
return this;
}
/**
* When allowing assets to be created, how to handle those creations (full assets or partial assets).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder creationHandling(final AssetCreationHandling creationHandling) {
this.creationHandling$value = creationHandling;
creationHandling$set = true;
return this;
}
/**
* Whether tables and views should be treated interchangeably (an asset in the batch marked as a table will attempt to match a view if not found as a table, and vice versa).
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch.ParallelBatchBuilder tableViewAgnostic(final boolean tableViewAgnostic) {
this.tableViewAgnostic$value = tableViewAgnostic;
tableViewAgnostic$set = true;
return this;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public ParallelBatch build() {
int maxSize$value = this.maxSize$value;
if (!this.maxSize$set) maxSize$value = ParallelBatch.$default$maxSize();
boolean replaceAtlanTags$value = this.replaceAtlanTags$value;
if (!this.replaceAtlanTags$set) replaceAtlanTags$value = ParallelBatch.$default$replaceAtlanTags();
AssetBatch.CustomMetadataHandling customMetadataHandling$value = this.customMetadataHandling$value;
if (!this.customMetadataHandling$set) customMetadataHandling$value = ParallelBatch.$default$customMetadataHandling();
boolean captureFailures$value = this.captureFailures$value;
if (!this.captureFailures$set) captureFailures$value = ParallelBatch.$default$captureFailures();
boolean track$value = this.track$value;
if (!this.track$set) track$value = ParallelBatch.$default$track();
boolean updateOnly$value = this.updateOnly$value;
if (!this.updateOnly$set) updateOnly$value = ParallelBatch.$default$updateOnly();
boolean caseSensitive$value = this.caseSensitive$value;
if (!this.caseSensitive$set) caseSensitive$value = ParallelBatch.$default$caseSensitive();
AssetCreationHandling creationHandling$value = this.creationHandling$value;
if (!this.creationHandling$set) creationHandling$value = ParallelBatch.$default$creationHandling();
boolean tableViewAgnostic$value = this.tableViewAgnostic$value;
if (!this.tableViewAgnostic$set) tableViewAgnostic$value = ParallelBatch.$default$tableViewAgnostic();
return new ParallelBatch(this.client, maxSize$value, replaceAtlanTags$value, customMetadataHandling$value, captureFailures$value, track$value, updateOnly$value, caseSensitive$value, creationHandling$value, tableViewAgnostic$value);
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public java.lang.String toString() {
return "ParallelBatch.ParallelBatchBuilder(client=" + this.client + ", maxSize$value=" + this.maxSize$value + ", replaceAtlanTags$value=" + this.replaceAtlanTags$value + ", customMetadataHandling$value=" + this.customMetadataHandling$value + ", captureFailures$value=" + this.captureFailures$value + ", track$value=" + this.track$value + ", updateOnly$value=" + this.updateOnly$value + ", caseSensitive$value=" + this.caseSensitive$value + ", creationHandling$value=" + this.creationHandling$value + ", tableViewAgnostic$value=" + this.tableViewAgnostic$value + ")";
}
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public static ParallelBatch.ParallelBatchBuilder builder() {
return new ParallelBatch.ParallelBatchBuilder();
}
}