mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-05 03:54:23 +00:00
GEN -19588 Sort Enum type Custom Property Values (#19637)
* GEN -19588 Sort Enum type Custom Property Values * fix py-tests * use streams for sorting
This commit is contained in:
parent
c43fa48d18
commit
c0eb7d08de
@ -93,7 +93,7 @@ EXPECTED_CUSTOM_PROPERTIES = [
|
||||
"description": "Rating of a table",
|
||||
"propertyType": {"name": "enum"},
|
||||
"customPropertyConfig": {
|
||||
"config": {"values": ["Good", "Average", "Bad"], "multiSelect": False},
|
||||
"config": {"values": ["Average", "Bad", "Good"], "multiSelect": False},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -111,34 +111,25 @@ public class TypeRegistry {
|
||||
}
|
||||
|
||||
public static String getCustomPropertyType(String entityType, String propertyName) {
|
||||
Type type = TypeRegistry.TYPES.get(entityType);
|
||||
if (type != null && type.getCustomProperties() != null) {
|
||||
for (CustomProperty property : type.getCustomProperties()) {
|
||||
if (property.getName().equals(propertyName)) {
|
||||
return property.getPropertyType().getName();
|
||||
}
|
||||
}
|
||||
String fqn = getCustomPropertyFQN(entityType, propertyName);
|
||||
CustomProperty property = CUSTOM_PROPERTIES.get(fqn);
|
||||
if (property == null) {
|
||||
throw EntityNotFoundException.byMessage(
|
||||
CatalogExceptionMessage.entityNotFound(propertyName, entityType));
|
||||
}
|
||||
throw EntityNotFoundException.byMessage(
|
||||
CatalogExceptionMessage.entityNotFound(Entity.TYPE, String.valueOf(type)));
|
||||
return property.getPropertyType().getName();
|
||||
}
|
||||
|
||||
public static String getCustomPropertyConfig(String entityType, String propertyName) {
|
||||
Type type = TypeRegistry.TYPES.get(entityType);
|
||||
if (type != null && type.getCustomProperties() != null) {
|
||||
for (CustomProperty property : type.getCustomProperties()) {
|
||||
if (property.getName().equals(propertyName)
|
||||
&& property.getCustomPropertyConfig() != null
|
||||
&& property.getCustomPropertyConfig().getConfig() != null) {
|
||||
Object config = property.getCustomPropertyConfig().getConfig();
|
||||
if (config instanceof String || config instanceof Integer) {
|
||||
return config.toString(); // for simple type config return as string
|
||||
} else {
|
||||
return JsonUtils.pojoToJson(
|
||||
config); // for complex object in config return as JSON string
|
||||
}
|
||||
}
|
||||
}
|
||||
String fqn = getCustomPropertyFQN(entityType, propertyName);
|
||||
CustomProperty property = CUSTOM_PROPERTIES.get(fqn);
|
||||
if (property != null
|
||||
&& property.getCustomPropertyConfig() != null
|
||||
&& property.getCustomPropertyConfig().getConfig() != null) {
|
||||
Object config = property.getCustomPropertyConfig().getConfig();
|
||||
return (config instanceof String || config instanceof Integer)
|
||||
? config.toString() // for simple type config return as string
|
||||
: JsonUtils.pojoToJson(config); // for complex object in config return as JSON string
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -111,6 +111,7 @@ import java.util.function.BiConsumer;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
import javax.json.JsonPatch;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.constraints.NotNull;
|
||||
@ -1663,7 +1664,16 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
jsonNode.put(fieldName, formattedValue);
|
||||
}
|
||||
case "table-cp" -> validateTableType(fieldValue, propertyConfig, fieldName);
|
||||
case "enum" -> validateEnumKeys(fieldName, fieldValue, propertyConfig);
|
||||
case "enum" -> {
|
||||
validateEnumKeys(fieldName, fieldValue, propertyConfig);
|
||||
List<String> enumValues =
|
||||
StreamSupport.stream(fieldValue.spliterator(), false)
|
||||
.map(JsonNode::asText)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
jsonNode.set(fieldName, JsonUtils.valueToTree(enumValues));
|
||||
entity.setExtension(jsonNode);
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
@ -1832,8 +1842,19 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
}
|
||||
ObjectNode objectNode = JsonUtils.getObjectNode();
|
||||
for (ExtensionRecord extensionRecord : records) {
|
||||
String fieldName = TypeRegistry.getPropertyName(extensionRecord.extensionName());
|
||||
objectNode.set(fieldName, JsonUtils.readTree(extensionRecord.extensionJson()));
|
||||
String fieldName = extensionRecord.extensionName().substring(fieldFQNPrefix.length() + 1);
|
||||
JsonNode fieldValue = JsonUtils.readTree(extensionRecord.extensionJson());
|
||||
String customPropertyType = TypeRegistry.getCustomPropertyType(entityType, fieldName);
|
||||
if ("enum".equals(customPropertyType) && fieldValue.isArray() && fieldValue.size() > 1) {
|
||||
List<String> sortedEnumValues =
|
||||
StreamSupport.stream(fieldValue.spliterator(), false)
|
||||
.map(JsonNode::asText)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
fieldValue = JsonUtils.valueToTree(sortedEnumValues);
|
||||
}
|
||||
|
||||
objectNode.set(fieldName, fieldValue);
|
||||
}
|
||||
return objectNode;
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
@ -174,6 +175,11 @@ public class TypeRepository extends EntityRepository<Type> {
|
||||
for (Triple<String, String, String> result : results) {
|
||||
CustomProperty property = JsonUtils.readValue(result.getRight(), CustomProperty.class);
|
||||
property.setPropertyType(this.getReferenceByName(result.getMiddle(), NON_DELETED));
|
||||
|
||||
if ("enum".equals(property.getPropertyType().getName())) {
|
||||
sortEnumKeys(property);
|
||||
}
|
||||
|
||||
customProperties.add(property);
|
||||
}
|
||||
customProperties.sort(EntityUtil.compareCustomProperty);
|
||||
@ -270,6 +276,19 @@ public class TypeRepository extends EntityRepository<Type> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void sortEnumKeys(CustomProperty property) {
|
||||
Object enumConfig = property.getCustomPropertyConfig().getConfig();
|
||||
if (enumConfig instanceof Map) {
|
||||
Map<String, Object> configMap = (Map<String, Object>) enumConfig;
|
||||
if (configMap.get("values") instanceof List) {
|
||||
List<String> values = (List<String>) configMap.get("values");
|
||||
List<String> sortedValues = values.stream().sorted().collect(Collectors.toList());
|
||||
configMap.put("values", sortedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Handles entity updated from PUT and POST operation. */
|
||||
public class TypeUpdater extends EntityUpdater {
|
||||
public TypeUpdater(Type original, Type updated, Operation operation) {
|
||||
@ -460,6 +479,7 @@ public class TypeRepository extends EntityRepository<Type> {
|
||||
Type entity, CustomProperty origProperty, CustomProperty updatedProperty) {
|
||||
String updatedBy = entity.getUpdatedBy();
|
||||
if (origProperty.getPropertyType().getName().equals("enum")) {
|
||||
sortEnumKeys(updatedProperty);
|
||||
EnumConfig origConfig =
|
||||
JsonUtils.convertValue(
|
||||
origProperty.getCustomPropertyConfig().getConfig(), EnumConfig.class);
|
||||
|
||||
@ -875,7 +875,12 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
.withConfig(
|
||||
Map.of(
|
||||
"values",
|
||||
List.of("single1", "single2", "single3", "single4", "\"single5\""),
|
||||
List.of(
|
||||
"\"single val with quotes\"",
|
||||
"single1",
|
||||
"single2",
|
||||
"single3",
|
||||
"single4"),
|
||||
"multiSelect",
|
||||
false))),
|
||||
new CustomProperty()
|
||||
@ -916,7 +921,7 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
",g1,dsp1,\"dsc1,1\",h1;h2;h3,g1.g1t1;g2.g2t1,term1;http://term1,PII.None,user:%s,user:%s,%s,\"glossaryTermDateCp:18-09-2024;glossaryTermDateTimeCp:18-09-2024 01:09:34;glossaryTermDurationCp:PT5H30M10S;glossaryTermEmailCp:admin@open-metadata.org;glossaryTermEntRefCp:team:\"\"%s\"\";glossaryTermEntRefListCp:user:\"\"%s\"\"|user:\"\"%s\"\"\"",
|
||||
reviewerRef.get(0), user1, "Approved", team11, user1, user2),
|
||||
String.format(
|
||||
",g2,dsp2,dsc3,h1;h3;h3,g1.g1t1;g2.g2t1,term2;https://term2,PII.NonSensitive,,user:%s,%s,\"glossaryTermEnumCpMulti:val3|val2|val1|val4|val5;glossaryTermEnumCpSingle:single1;glossaryTermIntegerCp:7777;glossaryTermMarkdownCp:# Sample Markdown Text;glossaryTermNumberCp:123456;\"\"glossaryTermQueryCp:select col,row from table where id ='30';\"\";glossaryTermStringCp:sample string content;glossaryTermTimeCp:10:08:45;glossaryTermTimeIntervalCp:1726142300000:17261420000;glossaryTermTimestampCp:1726142400000\"",
|
||||
",g2,dsp2,dsc3,h1;h3;h3,g1.g1t1;g2.g2t1,term2;https://term2,PII.NonSensitive,,user:%s,%s,\"glossaryTermEnumCpMulti:val1|val2|val3|val4|val5;glossaryTermEnumCpSingle:single1;glossaryTermIntegerCp:7777;glossaryTermMarkdownCp:# Sample Markdown Text;glossaryTermNumberCp:123456;\"\"glossaryTermQueryCp:select col,row from table where id ='30';\"\";glossaryTermStringCp:sample string content;glossaryTermTimeCp:10:08:45;glossaryTermTimeIntervalCp:1726142300000:17261420000;glossaryTermTimestampCp:1726142400000\"",
|
||||
user1, "Approved"),
|
||||
String.format(
|
||||
"importExportTest.g1,g11,dsp2,dsc11,h1;h3;h3,g1.g1t1;g2.g2t1,,,user:%s,team:%s,%s,",
|
||||
@ -929,7 +934,7 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
",g1,dsp1,new-dsc1,h1;h2;h3,g1.g1t1;importExportTest.g2;g2.g2t1,term1;http://term1,PII.None,user:%s,user:%s,%s,\"glossaryTermDateCp:18-09-2024;glossaryTermDateTimeCp:18-09-2024 01:09:34;glossaryTermDurationCp:PT5H30M10S;glossaryTermEmailCp:admin@open-metadata.org;glossaryTermEntRefCp:team:\"\"%s\"\";glossaryTermEntRefListCp:user:\"\"%s\"\"|user:\"\"%s\"\"\"",
|
||||
reviewerRef.get(0), user1, "Approved", team11, user1, user2),
|
||||
String.format(
|
||||
",g2,dsp2,new-dsc3,h1;h3;h3,importExportTest.g1;g1.g1t1;g2.g2t1,term2;https://term2,PII.NonSensitive,user:%s,user:%s,%s,\"glossaryTermEnumCpMulti:val3|val2|val1|val4|val5;glossaryTermEnumCpSingle:single1;glossaryTermIntegerCp:7777;glossaryTermMarkdownCp:# Sample Markdown Text;glossaryTermNumberCp:123456;\"\"glossaryTermQueryCp:select col,row from table where id ='30';\"\";glossaryTermStringCp:sample string content;glossaryTermTimeCp:10:08:45;glossaryTermTimeIntervalCp:1726142300000:17261420000;glossaryTermTimestampCp:1726142400000\"",
|
||||
",g2,dsp2,new-dsc3,h1;h3;h3,importExportTest.g1;g1.g1t1;g2.g2t1,term2;https://term2,PII.NonSensitive,user:%s,user:%s,%s,\"glossaryTermEnumCpMulti:val1|val2|val3|val4|val5;glossaryTermEnumCpSingle:single1;glossaryTermIntegerCp:7777;glossaryTermMarkdownCp:# Sample Markdown Text;glossaryTermNumberCp:123456;\"\"glossaryTermQueryCp:select col,row from table where id ='30';\"\";glossaryTermStringCp:sample string content;glossaryTermTimeCp:10:08:45;glossaryTermTimeIntervalCp:1726142300000:17261420000;glossaryTermTimestampCp:1726142400000\"",
|
||||
user1, user2, "Approved"),
|
||||
String.format(
|
||||
"importExportTest.g1,g11,dsp2,new-dsc11,h1;h3;h3,,,,user:%s,team:%s,%s,\"\"\"glossaryTermTableCol1Cp:row_1_col1_Value,,\"\";\"\"glossaryTermTableCol3Cp:row_1_col1_Value,row_1_col2_Value,row_1_col3_Value|row_2_col1_Value,row_2_col2_Value,row_2_col3_Value\"\"\"",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user