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.
/* SPDX-License-Identifier: Apache-2.0
Copyright 2022 Atlan Pte. Ltd. */
package com.atlan.serde;
import com.atlan.AtlanClient;
import com.atlan.cache.ReflectionCache;
import com.atlan.exception.AtlanException;
import com.atlan.exception.NotFoundException;
import com.atlan.model.assets.Asset;
import com.atlan.model.core.CustomMetadataAttributes;
import com.atlan.model.relations.Reference;
import com.atlan.util.StringUtils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.*;
/**
* Serialization of all {@link Asset} objects, down through the entire inheritance hierarchy.
* This custom serialization is necessary to create some specific aspects of complexity in Atlan's payloads:
*
*
The nested attributes and relationshipAttributes structures.
*
Handling the extension of properties as you traverse down the inheritance structures, without needing to also extend these nested structures through inheritance.
*
Automatically translating custom metadata into the nested businessAttributes structure, including translating human-readable names into Atlan's internal hashed-string representations.
*
*/
public class AssetSerializer extends StdSerializer {
private static final long serialVersionUID = 2L;
private final AtlanClient client;
public AssetSerializer(AtlanClient client) {
this(Asset.class, client);
}
public AssetSerializer(Class t, AtlanClient client) {
super(t);
this.client = client;
}
/**
* {@inheritDoc}
*/
@Override
public void serializeWithType(
Asset value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
serialize(value, gen, serializers);
}
/**
* {@inheritDoc}
*/
@Override
public void serialize(Asset asset, JsonGenerator gen, SerializerProvider sp)
throws IOException, JsonProcessingException {
Class> clazz = asset.getClass();
Set nullFields = asset.getNullFields();
Map attributes = new LinkedHashMap<>();
Map appendRelationships = new LinkedHashMap<>();
Map removeRelationships = new LinkedHashMap<>();
Map> businessAttributes = new LinkedHashMap<>();
gen.writeStartObject();
try {
for (String fieldName : ReflectionCache.getFieldNames(clazz)) {
if (ReflectionCache.isAttribute(clazz, fieldName)) {
// If the field should be attribute-nested...
Object attrValue;
Class> type = ReflectionCache.getFieldType(clazz, fieldName);
if (nullFields.contains(fieldName)) {
// If the value should be serialized as null, then
// set the value to the serializable null
if (type == List.class || type == Set.class || type == SortedSet.class) {
attrValue = Removable.EMPTY_LIST;
} else {
attrValue = Removable.NULL;
}
} else {
// Otherwise, pickup the value from the top-level
// attribute so that we can move that value across
attrValue = ReflectionCache.getValue(asset, fieldName);
}
if (attrValue != null) {
// Ignore null values and empty collections
boolean skip = (attrValue instanceof Collection && ((Collection>) attrValue).isEmpty())
|| (attrValue instanceof Map && ((Map, ?>) attrValue).isEmpty());
if (!skip) {
if (fieldName.equals("mappedAtlanTagName")) {
String mappedName;
try {
mappedName = client.getAtlanTagCache().getIdForName(attrValue.toString());
} catch (NotFoundException e) {
mappedName = Serde.DELETED_AUDIT_OBJECT;
} catch (AtlanException e) {
throw new IOException("Unable to serialize mappedAtlanTagName.", e);
}
attrValue = mappedName;
} else if (fieldName.equals("purposeAtlanTags") && attrValue instanceof Collection) {
List mappedNames = new ArrayList<>();
for (Object one : (Collection>) attrValue) {
try {
mappedNames.add(
client.getAtlanTagCache().getIdForName(one.toString()));
} catch (NotFoundException e) {
mappedNames.add(Serde.DELETED_AUDIT_OBJECT);
} catch (AtlanException e) {
throw new IOException("Unable to serialize purposeAtlanTags.", e);
}
}
attrValue = mappedNames;
}
// Add the value we've derived above to the attribute map for nesting
String serializeName = ReflectionCache.getSerializedName(clazz, fieldName);
// Note: the value could be a singular reference, or a collection of references...
if (attrValue instanceof Collection) {
// If it is in a collection, check whether the first value is a reference
// (there should always be one, as earlier condition would exclude empty
// collections)
Collection> values = (Collection>) attrValue;
Optional> first = values.stream().findFirst();
if (first.isPresent() && first.get() instanceof Reference) {
List