Skip to content

Commit

Permalink
feat(structuredProperties) Add new settings aspect plus graphql chang…
Browse files Browse the repository at this point in the history
…es for structured props (#12052)
  • Loading branch information
chriscollins3456 authored Dec 11, 2024
1 parent b091e46 commit f1ef4f8
Show file tree
Hide file tree
Showing 37 changed files with 913 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.linkedin.datahub.graphql.resolvers.structuredproperties;

import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.bindArgument;
import static com.linkedin.metadata.Constants.STRUCTURED_PROPERTY_ENTITY_NAME;
import static com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils.buildMetadataChangeProposalWithUrn;
import static com.linkedin.metadata.Constants.*;

import com.linkedin.common.urn.Urn;
import com.linkedin.data.template.SetMode;
Expand All @@ -12,20 +13,24 @@
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.CreateStructuredPropertyInput;
import com.linkedin.datahub.graphql.generated.StructuredPropertyEntity;
import com.linkedin.datahub.graphql.generated.StructuredPropertySettingsInput;
import com.linkedin.datahub.graphql.types.structuredproperty.StructuredPropertyMapper;
import com.linkedin.entity.EntityResponse;
import com.linkedin.entity.client.EntityClient;
import com.linkedin.metadata.aspect.patch.builder.StructuredPropertyDefinitionPatchBuilder;
import com.linkedin.metadata.models.StructuredPropertyUtils;
import com.linkedin.metadata.utils.EntityKeyUtils;
import com.linkedin.mxe.MetadataChangeProposal;
import com.linkedin.structured.PrimitivePropertyValue;
import com.linkedin.structured.PropertyCardinality;
import com.linkedin.structured.PropertyValue;
import com.linkedin.structured.StructuredPropertyKey;
import com.linkedin.structured.StructuredPropertySettings;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;

Expand Down Expand Up @@ -54,40 +59,28 @@ public CompletableFuture<StructuredPropertyEntity> get(final DataFetchingEnviron
"Unable to create structured property. Please contact your admin.");
}
final StructuredPropertyKey key = new StructuredPropertyKey();
final String id = input.getId() != null ? input.getId() : UUID.randomUUID().toString();
final String id =
StructuredPropertyUtils.getPropertyId(input.getId(), input.getQualifiedName());
key.setId(id);
final Urn propertyUrn =
EntityKeyUtils.convertEntityKeyToUrn(key, STRUCTURED_PROPERTY_ENTITY_NAME);
StructuredPropertyDefinitionPatchBuilder builder =
new StructuredPropertyDefinitionPatchBuilder().urn(propertyUrn);

builder.setQualifiedName(input.getQualifiedName());
builder.setValueType(input.getValueType());
input.getEntityTypes().forEach(builder::addEntityType);
if (input.getDisplayName() != null) {
builder.setDisplayName(input.getDisplayName());
}
if (input.getDescription() != null) {
builder.setDescription(input.getDescription());
}
if (input.getImmutable() != null) {
builder.setImmutable(input.getImmutable());
}
if (input.getTypeQualifier() != null) {
buildTypeQualifier(input, builder);
}
if (input.getAllowedValues() != null) {
buildAllowedValues(input, builder);

if (_entityClient.exists(context.getOperationContext(), propertyUrn)) {
throw new IllegalArgumentException(
"A structured property already exists with this urn");
}
if (input.getCardinality() != null) {
builder.setCardinality(
PropertyCardinality.valueOf(input.getCardinality().toString()));

List<MetadataChangeProposal> mcps = new ArrayList<>();

// first, create the property definition itself
mcps.add(createPropertyDefinition(context, propertyUrn, id, input));

// then add the settings aspect if we're adding any settings inputs
if (input.getSettings() != null) {
mcps.add(createPropertySettings(context, propertyUrn, input.getSettings()));
}
builder.setCreated(context.getOperationContext().getAuditStamp());
builder.setLastModified(context.getOperationContext().getAuditStamp());

MetadataChangeProposal mcp = builder.build();
_entityClient.ingestProposal(context.getOperationContext(), mcp, false);
_entityClient.batchIngestProposals(context.getOperationContext(), mcps, false);

EntityResponse response =
_entityClient.getV2(
Expand All @@ -103,6 +96,72 @@ public CompletableFuture<StructuredPropertyEntity> get(final DataFetchingEnviron
});
}

private MetadataChangeProposal createPropertySettings(
@Nonnull final QueryContext context,
@Nonnull final Urn propertyUrn,
final StructuredPropertySettingsInput settingsInput)
throws Exception {
StructuredPropertySettings settings = new StructuredPropertySettings();

if (settingsInput.getIsHidden() != null) {
settings.setIsHidden(settingsInput.getIsHidden());
}
if (settingsInput.getShowInSearchFilters() != null) {
settings.setShowInSearchFilters(settingsInput.getShowInSearchFilters());
}
if (settingsInput.getShowInAssetSummary() != null) {
settings.setShowInAssetSummary(settingsInput.getShowInAssetSummary());
}
if (settingsInput.getShowAsAssetBadge() != null) {
settings.setShowAsAssetBadge(settingsInput.getShowAsAssetBadge());
}
if (settingsInput.getShowInColumnsTable() != null) {
settings.setShowInColumnsTable(settingsInput.getShowInColumnsTable());
}
settings.setLastModified(context.getOperationContext().getAuditStamp());

StructuredPropertyUtils.validatePropertySettings(settings, true);

return buildMetadataChangeProposalWithUrn(
propertyUrn, STRUCTURED_PROPERTY_SETTINGS_ASPECT_NAME, settings);
}

private MetadataChangeProposal createPropertyDefinition(
@Nonnull final QueryContext context,
@Nonnull final Urn propertyUrn,
@Nonnull final String id,
final CreateStructuredPropertyInput input)
throws Exception {
StructuredPropertyDefinitionPatchBuilder builder =
new StructuredPropertyDefinitionPatchBuilder().urn(propertyUrn);

builder.setQualifiedName(id);
builder.setValueType(input.getValueType());
input.getEntityTypes().forEach(builder::addEntityType);
if (input.getDisplayName() != null) {
builder.setDisplayName(input.getDisplayName());
}
if (input.getDescription() != null) {
builder.setDescription(input.getDescription());
}
if (input.getImmutable() != null) {
builder.setImmutable(input.getImmutable());
}
if (input.getTypeQualifier() != null) {
buildTypeQualifier(input, builder);
}
if (input.getAllowedValues() != null) {
buildAllowedValues(input, builder);
}
if (input.getCardinality() != null) {
builder.setCardinality(PropertyCardinality.valueOf(input.getCardinality().toString()));
}
builder.setCreated(context.getOperationContext().getAuditStamp());
builder.setLastModified(context.getOperationContext().getAuditStamp());

return builder.build();
}

private void buildTypeQualifier(
@Nonnull final CreateStructuredPropertyInput input,
@Nonnull final StructuredPropertyDefinitionPatchBuilder builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.linkedin.common.urn.UrnUtils;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.DeleteStructuredPropertyInput;
import com.linkedin.entity.client.EntityClient;
Expand Down Expand Up @@ -42,6 +43,23 @@ public CompletableFuture<Boolean> get(final DataFetchingEnvironment environment)
"Unable to delete structured property. Please contact your admin.");
}
_entityClient.deleteEntity(context.getOperationContext(), propertyUrn);
// Asynchronously Delete all references to the entity (to return quickly)
GraphQLConcurrencyUtils.supplyAsync(
() -> {
try {
_entityClient.deleteEntityReferences(
context.getOperationContext(), propertyUrn);
} catch (Exception e) {
log.error(
String.format(
"Caught exception while attempting to clear all entity references for Structured Property with urn %s",
propertyUrn),
e);
}
return null;
},
this.getClass().getSimpleName(),
"get");
return true;
} catch (Exception e) {
throw new RuntimeException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public CompletableFuture<com.linkedin.datahub.graphql.generated.StructuredProper
.getValue()
.data());

return StructuredPropertiesMapper.map(context, structuredProperties);
return StructuredPropertiesMapper.map(context, structuredProperties, assetUrn);
} catch (Exception e) {
throw new RuntimeException(
String.format("Failed to perform update against input %s", input), e);
Expand Down
Loading

0 comments on commit f1ef4f8

Please sign in to comment.