Commit add9fac4 by Merryle Wang Committed by Sarath Subramanian

ATLAS-3343: Ordering of dynAttr evaluation

parent 5b8b16eb
...@@ -687,6 +687,9 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -687,6 +687,9 @@ public class AtlasEntityType extends AtlasStructType {
} }
} }
//reorder dynAttributes in a topological sort
dynAttributes = reorderDynAttributes();
for (List<TemplateToken> parsedTemplate : parsedTemplates.values()) { for (List<TemplateToken> parsedTemplate : parsedTemplates.values()) {
for (TemplateToken token : parsedTemplate) { for (TemplateToken token : parsedTemplate) {
// If token is an instance of AttributeToken means that the attribute is of this entity type // 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 { ...@@ -1000,4 +1003,57 @@ public class AtlasEntityType extends AtlasStructType {
return ret; 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;
}
} }
...@@ -44,6 +44,8 @@ public class TestAtlasEntityType { ...@@ -44,6 +44,8 @@ public class TestAtlasEntityType {
private static final String ATTR_COLUMNS = "columns"; private static final String ATTR_COLUMNS = "columns";
private static final String ATTR_OWNER = "owner"; private static final String ATTR_OWNER = "owner";
private static final String ATTR_NAME = "name"; 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 AtlasEntityType entityType;
private final List<Object> validValues = new ArrayList<>(); private final List<Object> validValues = new ArrayList<>();
...@@ -198,6 +200,38 @@ public class TestAtlasEntityType { ...@@ -198,6 +200,38 @@ public class TestAtlasEntityType {
} }
@Test @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() { public void testConstraintInvalidOwnedRef_InvalidAttributeType() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null; AtlasTransientTypeRegistry ttr = null;
...@@ -371,6 +405,42 @@ public class TestAtlasEntityType { ...@@ -371,6 +405,42 @@ public class TestAtlasEntityType {
return table; 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() { private AtlasEntityDef createTableEntityDefWithOwnedRefOnInvalidType() {
AtlasEntityDef table = new AtlasEntityDef(TYPE_TABLE); AtlasEntityDef table = new AtlasEntityDef(TYPE_TABLE);
AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING); AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment