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

sarath pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/branch-2.0 by this push:
     new 12bc1ae  ATLAS-3343: Ordering of dynAttr evaluation
12bc1ae is described below

commit 12bc1ae791dfbc715cb71c1f97207d81e530532d
Author: Merryle Wang <[email protected]>
AuthorDate: Thu Aug 8 11:25:22 2019 -0700

    ATLAS-3343: Ordering of dynAttr evaluation
    
    Signed-off-by: Sarath Subramanian <[email protected]>
    (cherry picked from commit add9fac419addf164fcfe1a35535080ca8b67543)
---
 .../org/apache/atlas/type/AtlasEntityType.java     | 56 +++++++++++++++
 .../org/apache/atlas/type/TestAtlasEntityType.java | 82 ++++++++++++++++++++--
 2 files changed, 132 insertions(+), 6 deletions(-)

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 23eaa0a..884447f 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
@@ -687,6 +687,9 @@ public class AtlasEntityType extends AtlasStructType {
             }
         }
 
+        //reorder dynAttributes in a topological sort
+        dynAttributes = reorderDynAttributes();
+
         for (List<TemplateToken> parsedTemplate : parsedTemplates.values()) {
             for (TemplateToken token : parsedTemplate) {
                 // If token is an instance of AttributeToken means that the 
attribute is of this entity type
@@ -1000,4 +1003,57 @@ public class AtlasEntityType extends AtlasStructType {
 
         return ret;
     }
+
+    private List<AtlasAttribute> reorderDynAttributes() {
+        Map<AtlasAttribute, List<AtlasAttribute>> adj = 
createTokenAttributesMap();
+
+        return topologicalSort(adj);
+    }
+
+    private List<AtlasAttribute> topologicalSort(Map<AtlasAttribute, 
List<AtlasAttribute>> adj){
+        List<AtlasAttribute> order   = new ArrayList<>();
+        Set<AtlasAttribute>  visited = new HashSet<>();
+
+        for (AtlasAttribute attribute : adj.keySet()) {
+            visitAttribute(attribute, visited, order, adj);
+        }
+
+        Collections.reverse(order);
+
+        return order;
+    }
+
+    private void visitAttribute(AtlasAttribute attribute, Set<AtlasAttribute> 
visited, List<AtlasAttribute> order, Map<AtlasAttribute, List<AtlasAttribute>> 
adj) {
+        if (!visited.contains(attribute)) {
+            visited.add(attribute);
+
+            for (AtlasAttribute neighbor : adj.get(attribute)) {
+                visitAttribute(neighbor, visited, order, adj);
+            }
+
+            order.add(attribute);
+        }
+    }
+
+    private Map<AtlasAttribute, List<AtlasAttribute>> 
createTokenAttributesMap() {
+        Map<AtlasAttribute, List<AtlasAttribute>> adj = new HashMap<>();
+
+        for (AtlasAttribute attribute : dynAttributes) {
+            adj.put(attribute, new ArrayList<>());
+        }
+
+        for (AtlasAttribute attribute : adj.keySet()) {
+            for (TemplateToken token : 
parsedTemplates.get(attribute.getName())) {
+                if (token instanceof AttributeToken) {
+                    AtlasAttribute tokenAttribute = 
getAttribute(token.getValue());
+
+                    if (adj.containsKey(tokenAttribute)) {
+                        adj.get(tokenAttribute).add(attribute);
+                    }
+                }
+            }
+        }
+
+        return adj;
+    }
 }
diff --git a/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java 
b/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java
index c114bdf..7429703 100644
--- a/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java
+++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java
@@ -38,12 +38,14 @@ import static org.testng.Assert.*;
 
 
 public class TestAtlasEntityType {
-    private static final String TYPE_TABLE   = "my_table";
-    private static final String TYPE_COLUMN  = "my_column";
-    private static final String ATTR_TABLE   = "table";
-    private static final String ATTR_COLUMNS = "columns";
-    private static final String ATTR_OWNER   = "owner";
-    private static final String ATTR_NAME    = "name";
+    private static final String TYPE_TABLE       = "my_table";
+    private static final String TYPE_COLUMN      = "my_column";
+    private static final String ATTR_TABLE       = "table";
+    private static final String ATTR_COLUMNS     = "columns";
+    private static final String ATTR_OWNER       = "owner";
+    private static final String ATTR_NAME        = "name";
+    private static final String ATTR_DESCRIPTION = "description";
+    private static final String ATTR_LOCATION    = "location";
 
     private final AtlasEntityType entityType;
     private final List<Object>    validValues   = new ArrayList<>();
@@ -198,6 +200,38 @@ public class TestAtlasEntityType {
     }
 
     @Test
+    public void testReorderDynAttributes() {
+        AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
+        AtlasTransientTypeRegistry ttr          = null;
+        boolean                    commit       = false;
+        List<AtlasEntityDef>       entityDefs   = new ArrayList<>();
+        String                     failureMsg   = null;
+
+        entityDefs.add(createTableEntityDefForTopSort());
+
+        try {
+            ttr = typeRegistry.lockTypeRegistryForUpdate();
+
+            ttr.addTypes(entityDefs);
+            //options are read in the table,
+            AtlasEntityType typeTable  = ttr.getEntityTypeByName(TYPE_TABLE);
+
+            // Expect attributes in this order: ATTR_DESCRIPTION, ATTR_OWNER, 
ATTR_NAME, ATTR_LOCATION
+            assertEquals(typeTable.getDynEvalAttributes().get(0).getName(), 
ATTR_DESCRIPTION);
+            assertEquals(typeTable.getDynEvalAttributes().get(1).getName(), 
ATTR_OWNER);
+            assertEquals(typeTable.getDynEvalAttributes().get(2).getName(), 
ATTR_NAME);
+            assertEquals(typeTable.getDynEvalAttributes().get(3).getName(), 
ATTR_LOCATION);
+
+            commit = true;
+        } catch (AtlasBaseException excp) {
+            failureMsg = excp.getMessage();
+        } finally {
+            typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
+        }
+        assertNull(failureMsg, "failed to create types " + TYPE_TABLE + " and 
" + TYPE_COLUMN);
+    }
+
+    @Test
     public void testConstraintInvalidOwnedRef_InvalidAttributeType() {
         AtlasTypeRegistry          typeRegistry = new AtlasTypeRegistry();
         AtlasTransientTypeRegistry ttr          = null;
@@ -371,6 +405,42 @@ public class TestAtlasEntityType {
         return table;
     }
 
+    private AtlasEntityDef createTableEntityDefForTopSort() {
+        AtlasEntityDef    table           = new AtlasEntityDef(TYPE_TABLE);
+        AtlasAttributeDef attrName        = new AtlasAttributeDef(ATTR_NAME, 
AtlasBaseTypeDef.ATLAS_TYPE_STRING);
+        AtlasAttributeDef attrOwner       = new AtlasAttributeDef(ATTR_OWNER, 
AtlasBaseTypeDef.ATLAS_TYPE_STRING);
+        AtlasAttributeDef attrDescription = new 
AtlasAttributeDef(ATTR_DESCRIPTION, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
+        AtlasAttributeDef attrLocation    = new 
AtlasAttributeDef(ATTR_LOCATION, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
+
+        table.addAttribute(attrName);
+        table.addAttribute(attrOwner);
+        table.addAttribute(attrDescription);
+        table.addAttribute(attrLocation);
+
+        Map<String,String> options = new HashMap<>();
+
+        String key1   = "dynAttribute:" + ATTR_OWNER;
+        String value1 = "{" + ATTR_DESCRIPTION + "}";
+
+        String key2   = "dynAttribute:" + ATTR_DESCRIPTION;
+        String value2 = "template";
+
+        String key3   = "dynAttribute:" + ATTR_NAME;
+        String value3 = "{" + ATTR_DESCRIPTION + "}@{" + ATTR_OWNER + "}";
+
+        String key4   = "dynAttribute:" + ATTR_LOCATION;
+        String value4 = "{" + ATTR_NAME + "}@{" + ATTR_OWNER + "}";
+
+        options.put(key1, value1);
+        options.put(key2, value2);
+        options.put(key3, value3);
+        options.put(key4, value4);
+
+        table.setOptions(options);
+
+        return table;
+    }
+
     private AtlasEntityDef createTableEntityDefWithOwnedRefOnInvalidType() {
         AtlasEntityDef    table    = new AtlasEntityDef(TYPE_TABLE);
         AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, 
AtlasBaseTypeDef.ATLAS_TYPE_STRING);

Reply via email to