You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2020/04/03 07:04:22 UTC

[atlas] branch master updated: ATLAS-3716: updated entity-def to support displayTextAttribute option

This is an automated email from the ASF dual-hosted git repository.

madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/master by this push:
     new 076d83c  ATLAS-3716: updated entity-def to support displayTextAttribute option
076d83c is described below

commit 076d83c3face54b53159faa066e398f622d836b0
Author: Madhan Neethiraj <ma...@apache.org>
AuthorDate: Thu Apr 2 10:59:40 2020 -0700

    ATLAS-3716: updated entity-def to support displayTextAttribute option
---
 addons/models/1000-Hadoop/1030-hive_model.json     |  7 ++-
 ..._process_execution_add_display_text_option.json | 15 +++++++
 .../atlas/model/typedef/AtlasBaseTypeDef.java      | 19 ++++++++
 .../apache/atlas/model/typedef/AtlasEntityDef.java |  2 +
 .../org/apache/atlas/type/AtlasEntityType.java     | 50 ++++++++++++++++++++--
 .../apache/atlas/type/TestAtlasTypeRegistry.java   | 32 +++++++++++++-
 .../store/graph/v2/EntityGraphRetriever.java       | 26 +++++++----
 .../org/apache/atlas/examples/QuickStartV2.java    |  2 +
 8 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/addons/models/1000-Hadoop/1030-hive_model.json b/addons/models/1000-Hadoop/1030-hive_model.json
index 8901aa4..b44f724 100644
--- a/addons/models/1000-Hadoop/1030-hive_model.json
+++ b/addons/models/1000-Hadoop/1030-hive_model.json
@@ -464,7 +464,7 @@
                 "ProcessExecution"
             ],
             "serviceType": "hive",
-            "typeVersion" : "1.0",
+            "typeVersion" : "1.1",
             "attributeDefs" : [
                 {
                     "name": "startTime",
@@ -530,7 +530,10 @@
                     "isOptional": false,
                     "isUnique": false
                 }
-            ]
+            ],
+            "options": {
+                "displayTextAttribute": "queryText"
+            }
         },
         {
             "name": "hive_db_ddl",
diff --git a/addons/models/1000-Hadoop/patches/016-hive_process_execution_add_display_text_option.json b/addons/models/1000-Hadoop/patches/016-hive_process_execution_add_display_text_option.json
new file mode 100644
index 0000000..cb15b34
--- /dev/null
+++ b/addons/models/1000-Hadoop/patches/016-hive_process_execution_add_display_text_option.json
@@ -0,0 +1,15 @@
+{
+  "patches": [
+    {
+      "id": "TYPEDEF_PATCH_1000_016_001",
+      "description": "Add 'displayTextAttribute' typeDefOptions to hive_process_execution",
+      "action": "UPDATE_TYPEDEF_OPTIONS",
+      "typeName": "hive_process_execution",
+      "applyToVersion": "1.0",
+      "updateToVersion": "1.1",
+      "typeDefOptions": {
+        "displayTextAttribute": "queryText"
+      }
+    }
+  ]
+}
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java
index eb86345..d461352 100644
--- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java
@@ -18,6 +18,7 @@
 package org.apache.atlas.model.typedef;
 
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import org.apache.atlas.model.TypeCategory;
@@ -307,6 +308,24 @@ public abstract class AtlasBaseTypeDef implements java.io.Serializable {
         }
     }
 
+    @JsonIgnore
+    public String getOption(String optionName) {
+        Map<String, String> options = this.options;
+
+        return options != null ? options.get(optionName) : null;
+    }
+
+    @JsonIgnore
+    public void setOption(String optionName, String value) {
+        Map<String, String> options = this.options;
+
+        if (options == null) {
+            this.options = options = new HashMap<>();
+        }
+
+        options.put(optionName, value);
+    }
+
     public StringBuilder toString(StringBuilder sb) {
         if (sb == null) {
             sb = new StringBuilder();
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasEntityDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasEntityDef.java
index 5bc6e97..d3356fa 100644
--- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasEntityDef.java
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasEntityDef.java
@@ -55,6 +55,8 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_
 public class AtlasEntityDef extends AtlasStructDef implements java.io.Serializable {
     private static final long serialVersionUID = 1L;
 
+    public static final String OPTION_DISPLAY_TEXT_ATTRIBUTE = "displayTextAttribute";
+
     private Set<String> superTypes;
 
     // this is a read-only field, any value provided during create & update operation is ignored
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
index b592701..3962c3c 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
@@ -86,6 +86,7 @@ public class AtlasEntityType extends AtlasStructType {
     private Map<String, Map<String, AtlasAttribute>>         relationshipAttributes     = Collections.emptyMap();
     private Map<String, Map<String, AtlasBusinessAttribute>> businessAttributes         = Collections.emptyMap();
     private List<AtlasAttribute>                             ownedRefAttributes         = Collections.emptyList();
+    private String                                           displayTextAttribute       = null;
     private String                                           typeAndAllSubTypesQryStr   = "";
     private boolean                                          isInternalType             = false;
     private Map<String, AtlasAttribute>                      headerAttributes           = Collections.emptyMap();
@@ -98,15 +99,17 @@ public class AtlasEntityType extends AtlasStructType {
     public AtlasEntityType(AtlasEntityDef entityDef) {
         super(entityDef);
 
-        this.entityDef  = entityDef;
-        this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
+        this.entityDef            = entityDef;
+        this.typeQryStr           = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
+        this.displayTextAttribute = entityDef.getOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE);
     }
 
     public AtlasEntityType(AtlasEntityDef entityDef, AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
         super(entityDef);
 
-        this.entityDef  = entityDef;
-        this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
+        this.entityDef            = entityDef;
+        this.typeQryStr           = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
+        this.displayTextAttribute = entityDef.getOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE);
 
         resolveReferences(typeRegistry);
     }
@@ -181,6 +184,29 @@ public class AtlasEntityType extends AtlasStructType {
                 }
             }
         }
+
+        if (this.displayTextAttribute != null) {
+            if (getAttribute(this.displayTextAttribute) == null) {
+                LOG.warn("{}: ignoring option {}, as attribute {} does not exist", getTypeName(), AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE, this.displayTextAttribute);
+
+                this.displayTextAttribute = null;
+            }
+        }
+
+        if (this.displayTextAttribute == null) { // find displayTextAttribute in direct superTypes
+            for (AtlasEntityType superType : superTypes) {
+                // read from superType's entityDef; not from superType.getDisplayTextAttribute(), as that might have been resolved to its superType
+                this.displayTextAttribute = superType.getEntityDef().getOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE);
+
+                if (this.displayTextAttribute != null) {
+                    if (getAttribute(this.displayTextAttribute) == null) { // if displayTextAttribute in superType is invalid, ignore
+                        this.displayTextAttribute = null;
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
     }
 
     @Override
@@ -321,6 +347,18 @@ public class AtlasEntityType extends AtlasStructType {
 
         entityDef.setBusinessAttributeDefs(bmAttributeDefs);
 
+        if (this.displayTextAttribute == null) {
+            for (String superTypeName : allSuperTypes) { // find displayTextAttribute in all superTypes
+                AtlasEntityType superType = typeRegistry.getEntityTypeByName(superTypeName);
+
+                this.displayTextAttribute = superType.getDisplayTextAttribute();
+
+                if (this.displayTextAttribute != null) {
+                    break;
+                }
+            }
+        }
+
         this.parsedTemplates = parseDynAttributeTemplates();
 
         populateDynFlagsInfo();
@@ -413,6 +451,10 @@ public class AtlasEntityType extends AtlasStructType {
         return ownedRefAttributes;
     }
 
+    public String getDisplayTextAttribute() {
+        return displayTextAttribute;
+    }
+
     public List<AtlasAttribute> getDynEvalAttributes() { return dynAttributes; }
 
     @VisibleForTesting
diff --git a/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java b/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java
index 945c06b..3b55a63 100644
--- a/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java
+++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java
@@ -26,6 +26,7 @@ import org.testng.annotations.Test;
 
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -219,7 +220,7 @@ public class TestAtlasTypeRegistry {
     }
 
     /*
-     *             L0
+     *             L0        L0_1
      *          /      \
      *         /         \
      *      L1_1----      L1_2
@@ -230,6 +231,7 @@ public class TestAtlasTypeRegistry {
     @Test
     public void testEntityDefValidHierarchy() throws AtlasBaseException {
         AtlasEntityDef entL0   = new AtlasEntityDef("L0");
+        AtlasEntityDef entL0_1 = new AtlasEntityDef("L0-1");
         AtlasEntityDef entL1_1 = new AtlasEntityDef("L1-1");
         AtlasEntityDef entL1_2 = new AtlasEntityDef("L1-2");
         AtlasEntityDef entL2_1 = new AtlasEntityDef("L2-1");
@@ -253,9 +255,16 @@ public class TestAtlasTypeRegistry {
         entL2_3.addAttribute(new AtlasAttributeDef("L2-3_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT));
         entL2_4.addAttribute(new AtlasAttributeDef("L2-4_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT));
 
+        // set displayNames in L0, L1_1, L2_1
+        entL0.setOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE, "L0_a1");
+        entL1_1.setOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE, "L1-1_a1");
+        entL2_1.setOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE, "L2-1_a1");
+        entL2_4.setOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE, "non-existing-attr");
+
         AtlasTypesDef typesDef = new AtlasTypesDef();
 
         typesDef.getEntityDefs().add(entL0);
+        typesDef.getEntityDefs().add(entL0_1);
         typesDef.getEntityDefs().add(entL1_1);
         typesDef.getEntityDefs().add(entL1_2);
         typesDef.getEntityDefs().add(entL2_1);
@@ -312,6 +321,15 @@ public class TestAtlasTypeRegistry {
         validateAttributeNames(typeRegistry, "L2-2", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L2-2_a1")));
         validateAttributeNames(typeRegistry, "L2-3", new HashSet<>(Arrays.asList("L0_a1", "L1-1_a1", "L1-2_a1", "L2-3_a1")));
         validateAttributeNames(typeRegistry, "L2-4", new HashSet<>(Arrays.asList("L0_a1", "L1-2_a1", "L2-4_a1")));
+
+        validateDisplayNameAttribute(typeRegistry, "L0", "L0_a1");     // directly assigned for this type
+        validateDisplayNameAttribute(typeRegistry, "L0-1");            // not assigned for this type
+        validateDisplayNameAttribute(typeRegistry, "L1-1", "L1-1_a1"); // directly assigned for this type
+        validateDisplayNameAttribute(typeRegistry, "L1-2", "L0_a1");   // inherits from L0
+        validateDisplayNameAttribute(typeRegistry, "L2-1", "L2-1_a1"); // directly assigned for this type
+        validateDisplayNameAttribute(typeRegistry, "L2-2", "L1-1_a1"); // inherits from L1-1
+        validateDisplayNameAttribute(typeRegistry, "L2-3", "L1-1_a1"); // inherits from L1-1 or L0
+        validateDisplayNameAttribute(typeRegistry, "L2-4", "L0_a1");   // invalid-name ignored, inherits from L0
     }
 
     @Test
@@ -678,4 +696,16 @@ public class TestAtlasTypeRegistry {
         assertNotNull(attributes);
         assertEquals(attributes.keySet(), attributeNames);
     }
+
+    private void validateDisplayNameAttribute(AtlasTypeRegistry typeRegistry, String entityTypeName, String... displayNameAttributes) {
+        AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entityTypeName);
+
+        if (displayNameAttributes == null || displayNameAttributes.length == 0) {
+            assertNull(entityType.getDisplayTextAttribute());
+        } else {
+            List<String> validValues = Arrays.asList(displayNameAttributes);
+
+            assertTrue(validValues.contains(entityType.getDisplayTextAttribute()), entityTypeName + ": invalid displayNameAttribute " + entityType.getDisplayTextAttribute() + ". Valid values: " + validValues);
+        }
+    }
 }
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
index 3a0d001..36bee30 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
@@ -704,8 +704,7 @@ public class EntityGraphRetriever {
                 }
             }
 
-            Object name        = ret.getAttribute(NAME);
-            Object displayText = name != null ? name : ret.getAttribute(QUALIFIED_NAME);
+            Object displayText = getDisplayText(entityVertex, entityType);
 
             if (displayText != null) {
                 ret.setDisplayText(displayText.toString());
@@ -1484,18 +1483,29 @@ public class EntityGraphRetriever {
     }
 
     private Object getDisplayText(AtlasVertex entityVertex, String entityTypeName) throws AtlasBaseException {
-        AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entityTypeName);
-        Object          ret        = null;
+        return getDisplayText(entityVertex, typeRegistry.getEntityTypeByName(entityTypeName));
+    }
+
+    private Object getDisplayText(AtlasVertex entityVertex, AtlasEntityType entityType) throws AtlasBaseException {
+        Object ret = null;
 
         if (entityType != null) {
-            ret = getVertexAttribute(entityVertex, entityType.getAttribute(NAME));
+            String displayTextAttribute = entityType.getDisplayTextAttribute();
 
-            if (ret == null) {
-                ret = getVertexAttribute(entityVertex, entityType.getAttribute(DISPLAY_NAME));
+            if (displayTextAttribute != null) {
+                ret = getVertexAttribute(entityVertex, entityType.getAttribute(displayTextAttribute));
             }
 
             if (ret == null) {
-                ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME));
+                ret = getVertexAttribute(entityVertex, entityType.getAttribute(NAME));
+
+                if (ret == null) {
+                    ret = getVertexAttribute(entityVertex, entityType.getAttribute(DISPLAY_NAME));
+
+                    if (ret == null) {
+                        ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME));
+                    }
+                }
             }
         }
 
diff --git a/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java b/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java
index 4474a28..b5d2a47 100755
--- a/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java
+++ b/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java
@@ -278,6 +278,8 @@ public class QuickStartV2 {
                 createRequiredAttrDef("queryId", "string"),
                 createRequiredAttrDef("queryGraph", "string"));
 
+        processExecutionTypeDef.setOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE, "queryText");
+
         AtlasEntityDef viewTypeDef    = createClassTypeDef(VIEW_TYPE, VIEW_TYPE, VERSION_1, Collections.singleton("DataSet"));
 
         // Relationship-Definitions