
com.atlan.util.AssetBatch Maven / Gradle / Ivy
// Generated by delombok at Wed Oct 16 22:16:02 UTC 2024
/* SPDX-License-Identifier: Apache-2.0
Copyright 2023 Atlan Pte. Ltd. */
package com.atlan.util;
import com.atlan.AtlanClient;
import com.atlan.cache.ReflectionCache;
import com.atlan.exception.AtlanException;
import com.atlan.exception.ErrorCode;
import com.atlan.exception.InvalidRequestException;
import com.atlan.exception.LogicException;
import com.atlan.model.assets.Asset;
import com.atlan.model.assets.Column;
import com.atlan.model.assets.IndistinctAsset;
import com.atlan.model.assets.MaterializedView;
import com.atlan.model.assets.Table;
import com.atlan.model.assets.View;
import com.atlan.model.core.AssetMutationResponse;
import com.atlan.model.core.AsyncCreationResponse;
import com.atlan.model.enums.AssetCreationHandling;
import com.atlan.model.relations.Reference;
import com.atlan.model.search.FluentSearch;
import com.atlan.serde.Serde;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
/**
* Utility class for managing bulk updates in batches.
*/
public class AssetBatch {
private static final Set TABLE_LEVEL_ASSETS = Set.of(Table.TYPE_NAME, View.TYPE_NAME, MaterializedView.TYPE_NAME);
public enum CustomMetadataHandling {
IGNORE, OVERWRITE, MERGE;
}
/**
* 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 CustomMetadataHandling customMetadataHandling;
/**
* Whether to capture details about any failures (true) or throw exceptions for any failures (false).
*/
private boolean captureFailures;
/**
* Whether to allow assets to be created (false) or only allow existing assets to be updated (true).
*/
private boolean updateOnly;
/**
* Whether to track the basic information about every asset that is created or updated (true) or only track counts (false).
*/
private boolean track;
/**
* When running with {@link #updateOnly} as true, whether to consider only exact matches (false) or ignore case (true).
*/
private boolean caseInsensitive;
/**
* 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;
/**
* Internal queue for building up assets to be saved.
*/
private final List _batch = Collections.synchronizedList(new ArrayList<>());
/**
* Number of assets that were created (no details, just a count).
*/
private final AtomicLong numCreated = new AtomicLong(0);
/**
* Number of assets that were updated (no details, just a count).
*/
private final AtomicLong numUpdated = new AtomicLong(0);
/**
* Number of assets that were potentially restored from being archived, or otherwise touched
* without actually being updated (no details, just a count).
*/
private final AtomicLong numRestored = new AtomicLong(0);
/**
* Assets that were created (minimal info only).
*/
private final List created = Collections.synchronizedList(new ArrayList<>());
/**
* Assets that were updated (minimal info only).
*/
private final List updated = Collections.synchronizedList(new ArrayList<>());
/**
* Assets that were potentially restored from being archived, or otherwise touched without actually
* being updated (minimal info only).
*/
private final List restored = Collections.synchronizedList(new ArrayList<>());
/**
* Batches that failed to be committed (only populated when captureFailures is set to true).
*/
private final List failures = Collections.synchronizedList(new ArrayList<>());
/**
* Assets that were skipped, when updateOnly is requested and the asset does not exist in Atlan.
*/
private final List skipped = Collections.synchronizedList(new ArrayList<>());
/**
* Map from placeholder GUID to resolved (actual) GUID, for all assets that were processed through the batch.
*/
private final Map resolvedGuids = new ConcurrentHashMap<>();
/**
* Map from all-lowercase qualifiedName (case-insensitive) to case-sensitive qualifiedName,
* for all assets that were processed through the batch.
* Note: This is only produced when caseInsensitive is true, otherwise it will be empty.
*/
private final Map resolvedQualifiedNames = new ConcurrentHashMap<>();
/**
* Create a new batch of assets to be bulk-saved.
*
* @param client connectivity to Atlan
* @param maxSize maximum size of each batch that should be processed (per API call)
*/
public AssetBatch(AtlanClient client, int maxSize) {
this(client, maxSize, false, CustomMetadataHandling.IGNORE);
}
/**
* Create a new batch of assets to be bulk-saved.
*
* @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 AssetBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, CustomMetadataHandling customMetadataHandling) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, false);
}
/**
* Create a new batch of assets to be bulk-saved.
*
* @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 AssetBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, CustomMetadataHandling customMetadataHandling, boolean captureFailures) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, false);
}
/**
* Create a new batch of assets to be bulk-saved.
*
* @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 AssetBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, true);
}
/**
* Create a new batch of assets to be bulk-saved.
*
* @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 AssetBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, track, false);
}
/**
* Create a new batch of assets to be bulk-saved.
*
* @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 caseInsensitive (only applies when updateOnly is true) when matching assets, search for their qualifiedName in a case-insensitive way
*/
public AssetBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track, boolean caseInsensitive) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, track, caseInsensitive, AssetCreationHandling.FULL);
}
/**
* Create a new batch of assets to be bulk-saved.
*
* @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 caseInsensitive (only applies when updateOnly is true) when matching assets, search for their qualifiedName in a case-insensitive way
* @param creationHandling if assets are to be created, how they should be created (as full assets or only partial assets)
*/
public AssetBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track, boolean caseInsensitive, AssetCreationHandling creationHandling) {
this(client, maxSize, replaceAtlanTags, customMetadataHandling, captureFailures, updateOnly, track, caseInsensitive, creationHandling, false);
}
/**
* Create a new batch of assets to be bulk-saved.
*
* @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 caseInsensitive (only applies when updateOnly is true) when matching assets, search for their qualifiedName in a case-insensitive way
* @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 AssetBatch(AtlanClient client, int maxSize, boolean replaceAtlanTags, CustomMetadataHandling customMetadataHandling, boolean captureFailures, boolean updateOnly, boolean track, boolean caseInsensitive, AssetCreationHandling creationHandling, boolean tableViewAgnostic) {
this.client = client;
this.maxSize = maxSize;
this.replaceAtlanTags = replaceAtlanTags;
this.customMetadataHandling = customMetadataHandling;
this.creationHandling = creationHandling;
this.track = track;
this.captureFailures = captureFailures;
this.updateOnly = updateOnly;
this.caseInsensitive = caseInsensitive;
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 {
_batch.add(single);
return process();
}
/**
* If the number of entities we have queued up is equal to the batch size, process them and reset our queue;
* otherwise do nothing.
*
* @return the assets that were created or updated in this batch, or null if the batch is still queued
* @throws AtlanException on any problems processing the batch
*/
private AssetMutationResponse process() throws AtlanException {
// Once we reach our batch size, create them and then start a new batch
if (_batch.size() == maxSize) {
return flush();
} else {
return null;
}
}
/**
* Flush any remaining assets in the batch.
*
* @return the mutation response from the queued batch of assets that were flushed
* @throws AtlanException on any problems flushing (submitting) the batch
*/
public AssetMutationResponse flush() throws AtlanException {
AsyncCreationResponse response = null;
List revised = null;
if (!_batch.isEmpty()) {
boolean fuzzyMatch = false;
if (tableViewAgnostic) {
Set typesInBatch = _batch.stream().map(Asset::getTypeName).collect(Collectors.toSet());
fuzzyMatch = typesInBatch.contains(Table.TYPE_NAME) || typesInBatch.contains(View.TYPE_NAME) || typesInBatch.contains(MaterializedView.TYPE_NAME);
}
if (updateOnly || creationHandling != AssetCreationHandling.FULL || fuzzyMatch) {
Map found = new HashMap<>();
List qualifiedNames = _batch.stream().map(Asset::getQualifiedName).collect(Collectors.toList());
FluentSearch.FluentSearchBuilder, ?> builder;
if (caseInsensitive) {
builder = client.assets.select(true).minSomes(1);
for (String qn : qualifiedNames) {
builder.whereSome(Asset.QUALIFIED_NAME.eq(qn, true));
}
} else {
builder = client.assets.select(true).where(Asset.QUALIFIED_NAME.in(qualifiedNames));
}
builder.pageSize(maxSize).stream().forEach(asset -> {
AssetIdentity assetId = new AssetIdentity(asset.getTypeName(), asset.getQualifiedName(), true);
found.put(assetId, asset.getQualifiedName());
});
revised = new ArrayList<>();
for (Asset asset : _batch) {
AssetIdentity assetId = new AssetIdentity(asset.getTypeName(), asset.getQualifiedName(), true);
// If found, with a type match, go ahead and update it
if (found.containsKey(assetId)) {
// Replace the actual qualifiedName on the asset before adding it to the batch
// (in case it matched case-insensitively, we need the proper case-sensitive name we
// found to ensure it's an update, not a create)
addFuzzyMatched(asset, asset.getTypeName(), found.get(assetId), revised);
} else if (tableViewAgnostic && TABLE_LEVEL_ASSETS.contains(asset.getTypeName())) {
// If found as a different (but acceptable) type, update that instead
AssetIdentity asTable = new AssetIdentity(Table.TYPE_NAME, asset.getQualifiedName(), true);
AssetIdentity asView = new AssetIdentity(View.TYPE_NAME, asset.getQualifiedName(), true);
AssetIdentity asMaterializedView = new AssetIdentity(MaterializedView.TYPE_NAME, asset.getQualifiedName(), true);
if (found.containsKey(asTable)) {
addFuzzyMatched(asset, Table.TYPE_NAME, found.get(asTable), revised);
} else if (found.containsKey(asView)) {
addFuzzyMatched(asset, View.TYPE_NAME, found.get(asView), revised);
} else if (found.containsKey(asMaterializedView)) {
addFuzzyMatched(asset, MaterializedView.TYPE_NAME, found.get(asMaterializedView), revised);
} else if (creationHandling == AssetCreationHandling.PARTIAL) {
// Still create it (partial), if not found and partial asset creation is allowed
addPartialAsset(asset, revised);
} else if (creationHandling == AssetCreationHandling.FULL) {
// Still create it (full), if not found and full asset creation is allowed
revised.addAll(_batch);
} else {
// Otherwise, if it still does not match any fallback and cannot be created, skip it
track(skipped, asset);
}
} else if (creationHandling == AssetCreationHandling.PARTIAL) {
// Append isPartial(true) onto the asset before adding it to the batch, to ensure only
// a partial (and not a full) asset is created
addPartialAsset(asset, revised);
} else {
track(skipped, asset);
}
}
} else {
// Otherwise create it (full)
revised = new ArrayList<>(_batch);
}
if (!revised.isEmpty()) {
try {
switch (customMetadataHandling) {
case IGNORE:
response = client.assets.save(revised, replaceAtlanTags);
break;
case OVERWRITE:
response = client.assets.saveReplacingCM(revised, replaceAtlanTags);
break;
case MERGE:
response = client.assets.saveMergingCM(revised, replaceAtlanTags);
break;
}
if (response != null) {
response.block();
}
} catch (AtlanException e) {
if (captureFailures) {
failures.add(new FailedBatch(_batch, e));
} else {
throw e;
}
}
}
_batch.clear();
}
trackResponse(response, revised);
return response;
}
private void addFuzzyMatched(Asset asset, String typeName, String actualQN, List revised) throws LogicException {
Reference.ReferenceBuilder, ?> assetBuilder = asset.toBuilder();
Method setQualifiedName = ReflectionCache.getSetter(assetBuilder.getClass(), Asset.QUALIFIED_NAME.getAtlanFieldName());
Method setTypeName = ReflectionCache.getSetter(assetBuilder.getClass(), Asset.TYPE_NAME.getAtlanFieldName());
try {
setTypeName.invoke(assetBuilder, typeName);
setQualifiedName.invoke(assetBuilder, actualQN);
revised.add((Asset) assetBuilder.build());
} catch (IllegalAccessException | InvocationTargetException e) {
throw new LogicException(ErrorCode.ASSET_MODIFICATION_ERROR, e, Asset.QUALIFIED_NAME.getAtlanFieldName() + " or " + Asset.TYPE_NAME.getAtlanFieldName());
}
}
private void addPartialAsset(Asset asset, List revised) throws LogicException {
Reference.ReferenceBuilder, ?> assetBuilder = asset.toBuilder();
Method setIsPartial = ReflectionCache.getSetter(assetBuilder.getClass(), Asset.IS_PARTIAL.getAtlanFieldName());
try {
setIsPartial.invoke(assetBuilder, true);
revised.add((Asset) assetBuilder.build());
} catch (IllegalAccessException | InvocationTargetException e) {
throw new LogicException(ErrorCode.ASSET_MODIFICATION_ERROR, e, Asset.QUALIFIED_NAME.getAtlanFieldName());
}
}
private void trackResponse(AssetMutationResponse response, List sent) {
if (response != null) {
if (track) {
response.getCreatedAssets().forEach(a -> track(created, a));
response.getUpdatedAssets().forEach(a -> track(updated, a));
}
// Always track the counts and resolved GUIDs...
numCreated.getAndAdd(response.getCreatedAssets().size());
numUpdated.getAndAdd(response.getUpdatedAssets().size());
if (response.getGuidAssignments() != null) {
resolvedGuids.putAll(response.getGuidAssignments());
}
if (sent != null) {
Set createdGuids = created.stream().map(Asset::getGuid).collect(Collectors.toSet());
Set updatedGuids = updated.stream().map(Asset::getGuid).collect(Collectors.toSet());
for (Asset one : sent) {
String guid = one.getGuid();
if (guid != null && (response.getGuidAssignments() == null || !response.getGuidAssignments().containsKey(guid))) {
// Ensure any assets that were sent with GUIDs that were used as-is
// are added to the resolved GUIDs map
resolvedGuids.put(guid, guid);
}
String mappedGuid = resolvedGuids.getOrDefault(guid, guid);
if (!createdGuids.contains(mappedGuid) && !updatedGuids.contains(mappedGuid)) {
// Ensure any assets that do not show as either created or updated are still tracked
// as possibly restored
track(restored, one);
numRestored.getAndIncrement();
}
if (caseInsensitive) {
String typeName = one.getTypeName();
String qualifiedName = one.getQualifiedName();
AssetIdentity id = new AssetIdentity(typeName, qualifiedName, true);
resolvedQualifiedNames.put(id, qualifiedName);
}
}
}
}
}
private void track(List tracker, Asset candidate) {
try {
tracker.add(buildCacheable(candidate.trimToRequired(), candidate));
} catch (InvalidRequestException e) {
try {
Class> assetClass = Serde.getAssetClassForType(candidate.getTypeName());
Method method = assetClass.getMethod("_internal");
Object result = method.invoke(null);
tracker.add(buildCacheable((Asset.AssetBuilder, ?>) result, candidate));
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException eRef) {
tracker.add(buildCacheable(IndistinctAsset._internal().typeName(candidate.getTypeName()), candidate));
}
}
}
/**
* Construct the minimal asset representation necessary for the asset to be included in a
* persistent connection cache.
*
* @param builder for the asset
* @param candidate from which to draw any additional details
* @return the minimally-complete, cacheable asset
*/
private Asset buildCacheable(Asset.AssetBuilder, ?> builder, Asset candidate) {
builder.guid(candidate.getGuid()).qualifiedName(candidate.getQualifiedName()).connectionQualifiedName(candidate.getConnectionQualifiedName()).name(candidate.getName()).tenantId(candidate.getTenantId());
if (candidate instanceof Column) {
Integer order = ((Column) candidate).getOrder();
if (order != null) {
((Column.ColumnBuilder, ?>) builder).order(order);
}
}
return builder.build();
}
/**
* Internal class to capture batch failures.
*/
public static final class FailedBatch {
private final List failedAssets;
private final Exception failureReason;
public FailedBatch(List failedAssets, Exception failureReason) {
this.failedAssets = List.copyOf(failedAssets);
this.failureReason = failureReason;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public List getFailedAssets() {
return this.failedAssets;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public Exception getFailureReason() {
return this.failureReason;
}
}
/**
* Class to uniquely identify an asset by its type and qualifiedName.
*/
public static final class AssetIdentity {
private final String typeName;
private final String qualifiedName;
public AssetIdentity(String typeName, String qualifiedName) {
this(typeName, qualifiedName, false);
}
public AssetIdentity(String typeName, String qualifiedName, boolean caseInsensitive) {
this.typeName = typeName;
if (caseInsensitive) {
this.qualifiedName = qualifiedName.toLowerCase(Locale.ROOT);
} else {
this.qualifiedName = qualifiedName;
}
}
@Override
public String toString() {
return typeName + "::" + qualifiedName;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public String getTypeName() {
return this.typeName;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public String getQualifiedName() {
return this.qualifiedName;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof AssetBatch.AssetIdentity)) return false;
final AssetBatch.AssetIdentity other = (AssetBatch.AssetIdentity) o;
final java.lang.Object this$typeName = this.getTypeName();
final java.lang.Object other$typeName = other.getTypeName();
if (this$typeName == null ? other$typeName != null : !this$typeName.equals(other$typeName)) return false;
final java.lang.Object this$qualifiedName = this.getQualifiedName();
final java.lang.Object other$qualifiedName = other.getQualifiedName();
if (this$qualifiedName == null ? other$qualifiedName != null : !this$qualifiedName.equals(other$qualifiedName)) return false;
return true;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $typeName = this.getTypeName();
result = result * PRIME + ($typeName == null ? 43 : $typeName.hashCode());
final java.lang.Object $qualifiedName = this.getQualifiedName();
result = result * PRIME + ($qualifiedName == null ? 43 : $qualifiedName.hashCode());
return result;
}
}
@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 CustomMetadataHandling $default$customMetadataHandling() {
return 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$updateOnly() {
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$caseInsensitive() {
return false;
}
@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 AssetBatchBuilder {
@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 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 updateOnly$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean updateOnly$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 caseInsensitive$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean caseInsensitive$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
AssetBatchBuilder() {
}
/**
* Connectivity to an Atlan tenant.
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public AssetBatch.AssetBatchBuilder 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 AssetBatch.AssetBatchBuilder 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 AssetBatch.AssetBatchBuilder 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 AssetBatch.AssetBatchBuilder customMetadataHandling(final 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 AssetBatch.AssetBatchBuilder captureFailures(final boolean captureFailures) {
this.captureFailures$value = captureFailures;
captureFailures$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 AssetBatch.AssetBatchBuilder updateOnly(final boolean updateOnly) {
this.updateOnly$value = updateOnly;
updateOnly$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 AssetBatch.AssetBatchBuilder track(final boolean track) {
this.track$value = track;
track$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 AssetBatch.AssetBatchBuilder caseInsensitive(final boolean caseInsensitive) {
this.caseInsensitive$value = caseInsensitive;
caseInsensitive$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 AssetBatch.AssetBatchBuilder 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 AssetBatch.AssetBatchBuilder tableViewAgnostic(final boolean tableViewAgnostic) {
this.tableViewAgnostic$value = tableViewAgnostic;
tableViewAgnostic$set = true;
return this;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public AssetBatch build() {
int maxSize$value = this.maxSize$value;
if (!this.maxSize$set) maxSize$value = AssetBatch.$default$maxSize();
boolean replaceAtlanTags$value = this.replaceAtlanTags$value;
if (!this.replaceAtlanTags$set) replaceAtlanTags$value = AssetBatch.$default$replaceAtlanTags();
CustomMetadataHandling customMetadataHandling$value = this.customMetadataHandling$value;
if (!this.customMetadataHandling$set) customMetadataHandling$value = AssetBatch.$default$customMetadataHandling();
boolean captureFailures$value = this.captureFailures$value;
if (!this.captureFailures$set) captureFailures$value = AssetBatch.$default$captureFailures();
boolean updateOnly$value = this.updateOnly$value;
if (!this.updateOnly$set) updateOnly$value = AssetBatch.$default$updateOnly();
boolean track$value = this.track$value;
if (!this.track$set) track$value = AssetBatch.$default$track();
boolean caseInsensitive$value = this.caseInsensitive$value;
if (!this.caseInsensitive$set) caseInsensitive$value = AssetBatch.$default$caseInsensitive();
AssetCreationHandling creationHandling$value = this.creationHandling$value;
if (!this.creationHandling$set) creationHandling$value = AssetBatch.$default$creationHandling();
boolean tableViewAgnostic$value = this.tableViewAgnostic$value;
if (!this.tableViewAgnostic$set) tableViewAgnostic$value = AssetBatch.$default$tableViewAgnostic();
return new AssetBatch(this.client, maxSize$value, replaceAtlanTags$value, customMetadataHandling$value, captureFailures$value, updateOnly$value, track$value, caseInsensitive$value, creationHandling$value, tableViewAgnostic$value);
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public java.lang.String toString() {
return "AssetBatch.AssetBatchBuilder(client=" + this.client + ", maxSize$value=" + this.maxSize$value + ", replaceAtlanTags$value=" + this.replaceAtlanTags$value + ", customMetadataHandling$value=" + this.customMetadataHandling$value + ", captureFailures$value=" + this.captureFailures$value + ", updateOnly$value=" + this.updateOnly$value + ", track$value=" + this.track$value + ", caseInsensitive$value=" + this.caseInsensitive$value + ", creationHandling$value=" + this.creationHandling$value + ", tableViewAgnostic$value=" + this.tableViewAgnostic$value + ")";
}
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public static AssetBatch.AssetBatchBuilder builder() {
return new AssetBatch.AssetBatchBuilder();
}
/**
* Number of assets that were created (no details, just a count).
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public AtomicLong getNumCreated() {
return this.numCreated;
}
/**
* Number of assets that were updated (no details, just a count).
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public AtomicLong getNumUpdated() {
return this.numUpdated;
}
/**
* Number of assets that were potentially restored from being archived, or otherwise touched
* without actually being updated (no details, just a count).
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public AtomicLong getNumRestored() {
return this.numRestored;
}
/**
* Assets that were created (minimal info only).
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public List getCreated() {
return this.created;
}
/**
* Assets that were updated (minimal info only).
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public List getUpdated() {
return this.updated;
}
/**
* Assets that were potentially restored from being archived, or otherwise touched without actually
* being updated (minimal info only).
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public List getRestored() {
return this.restored;
}
/**
* Batches that failed to be committed (only populated when captureFailures is set to true).
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public List getFailures() {
return this.failures;
}
/**
* Assets that were skipped, when updateOnly is requested and the asset does not exist in Atlan.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public List getSkipped() {
return this.skipped;
}
/**
* Map from placeholder GUID to resolved (actual) GUID, for all assets that were processed through the batch.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public Map getResolvedGuids() {
return this.resolvedGuids;
}
/**
* Map from all-lowercase qualifiedName (case-insensitive) to case-sensitive qualifiedName,
* for all assets that were processed through the batch.
* Note: This is only produced when caseInsensitive is true, otherwise it will be empty.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public Map getResolvedQualifiedNames() {
return this.resolvedQualifiedNames;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy