diff --git a/ingestion/tests/integration/ometa/test_ometa_custom_properties_api.py b/ingestion/tests/integration/ometa/test_ometa_custom_properties_api.py index 960a15adae9..cd8e7515fa6 100644 --- a/ingestion/tests/integration/ometa/test_ometa_custom_properties_api.py +++ b/ingestion/tests/integration/ometa/test_ometa_custom_properties_api.py @@ -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}, }, }, { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/TypeRegistry.java b/openmetadata-service/src/main/java/org/openmetadata/service/TypeRegistry.java index a294a79cc51..44cef8666f4 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/TypeRegistry.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/TypeRegistry.java @@ -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; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java index 636199c880d..9b831318d09 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java @@ -107,6 +107,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; @@ -1557,7 +1558,16 @@ public abstract class EntityRepository { jsonNode.put(fieldName, formattedValue); } case "table-cp" -> validateTableType(fieldValue, propertyConfig, fieldName); - case "enum" -> validateEnumKeys(fieldName, fieldValue, propertyConfig); + case "enum" -> { + validateEnumKeys(fieldName, fieldValue, propertyConfig); + List enumValues = + StreamSupport.stream(fieldValue.spliterator(), false) + .map(JsonNode::asText) + .sorted() + .collect(Collectors.toList()); + jsonNode.set(fieldName, JsonUtils.valueToTree(enumValues)); + entity.setExtension(jsonNode); + } default -> {} } } @@ -1704,8 +1714,19 @@ public abstract class EntityRepository { } 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 sortedEnumValues = + StreamSupport.stream(fieldValue.spliterator(), false) + .map(JsonNode::asText) + .sorted() + .collect(Collectors.toList()); + fieldValue = JsonUtils.valueToTree(sortedEnumValues); + } + + objectNode.set(fieldName, fieldValue); } return objectNode; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TypeRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TypeRepository.java index 8bde739c0b4..9c73d1a5502 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TypeRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TypeRepository.java @@ -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 { for (Triple 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 { } } + @SuppressWarnings("unchecked") + private void sortEnumKeys(CustomProperty property) { + Object enumConfig = property.getCustomPropertyConfig().getConfig(); + if (enumConfig instanceof Map) { + Map configMap = (Map) enumConfig; + if (configMap.get("values") instanceof List) { + List values = (List) configMap.get("values"); + List 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 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); diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java index b5e4ae27ac0..431daa668ae 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java @@ -870,7 +870,12 @@ public class GlossaryResourceTest extends EntityResourceTest