Commit 076d83c3 by Madhan Neethiraj

ATLAS-3716: updated entity-def to support displayTextAttribute option

parent 159afa80
...@@ -464,7 +464,7 @@ ...@@ -464,7 +464,7 @@
"ProcessExecution" "ProcessExecution"
], ],
"serviceType": "hive", "serviceType": "hive",
"typeVersion" : "1.0", "typeVersion" : "1.1",
"attributeDefs" : [ "attributeDefs" : [
{ {
"name": "startTime", "name": "startTime",
...@@ -530,7 +530,10 @@ ...@@ -530,7 +530,10 @@
"isOptional": false, "isOptional": false,
"isUnique": false "isUnique": false
} }
] ],
"options": {
"displayTextAttribute": "queryText"
}
}, },
{ {
"name": "hive_db_ddl", "name": "hive_db_ddl",
......
{
"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"
}
}
]
}
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
package org.apache.atlas.model.typedef; package org.apache.atlas.model.typedef;
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.apache.atlas.model.TypeCategory; import org.apache.atlas.model.TypeCategory;
...@@ -307,6 +308,24 @@ public abstract class AtlasBaseTypeDef implements java.io.Serializable { ...@@ -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) { public StringBuilder toString(StringBuilder sb) {
if (sb == null) { if (sb == null) {
sb = new StringBuilder(); sb = new StringBuilder();
......
...@@ -55,6 +55,8 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ ...@@ -55,6 +55,8 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_
public class AtlasEntityDef extends AtlasStructDef implements java.io.Serializable { public class AtlasEntityDef extends AtlasStructDef implements java.io.Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final String OPTION_DISPLAY_TEXT_ATTRIBUTE = "displayTextAttribute";
private Set<String> superTypes; private Set<String> superTypes;
// this is a read-only field, any value provided during create & update operation is ignored // this is a read-only field, any value provided during create & update operation is ignored
......
...@@ -86,6 +86,7 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -86,6 +86,7 @@ public class AtlasEntityType extends AtlasStructType {
private Map<String, Map<String, AtlasAttribute>> relationshipAttributes = Collections.emptyMap(); private Map<String, Map<String, AtlasAttribute>> relationshipAttributes = Collections.emptyMap();
private Map<String, Map<String, AtlasBusinessAttribute>> businessAttributes = Collections.emptyMap(); private Map<String, Map<String, AtlasBusinessAttribute>> businessAttributes = Collections.emptyMap();
private List<AtlasAttribute> ownedRefAttributes = Collections.emptyList(); private List<AtlasAttribute> ownedRefAttributes = Collections.emptyList();
private String displayTextAttribute = null;
private String typeAndAllSubTypesQryStr = ""; private String typeAndAllSubTypesQryStr = "";
private boolean isInternalType = false; private boolean isInternalType = false;
private Map<String, AtlasAttribute> headerAttributes = Collections.emptyMap(); private Map<String, AtlasAttribute> headerAttributes = Collections.emptyMap();
...@@ -100,6 +101,7 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -100,6 +101,7 @@ public class AtlasEntityType extends AtlasStructType {
this.entityDef = entityDef; this.entityDef = entityDef;
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName())); this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
this.displayTextAttribute = entityDef.getOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE);
} }
public AtlasEntityType(AtlasEntityDef entityDef, AtlasTypeRegistry typeRegistry) throws AtlasBaseException { public AtlasEntityType(AtlasEntityDef entityDef, AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
...@@ -107,6 +109,7 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -107,6 +109,7 @@ public class AtlasEntityType extends AtlasStructType {
this.entityDef = entityDef; this.entityDef = entityDef;
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName())); this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
this.displayTextAttribute = entityDef.getOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE);
resolveReferences(typeRegistry); resolveReferences(typeRegistry);
} }
...@@ -181,6 +184,29 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -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 @Override
...@@ -321,6 +347,18 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -321,6 +347,18 @@ public class AtlasEntityType extends AtlasStructType {
entityDef.setBusinessAttributeDefs(bmAttributeDefs); 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(); this.parsedTemplates = parseDynAttributeTemplates();
populateDynFlagsInfo(); populateDynFlagsInfo();
...@@ -413,6 +451,10 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -413,6 +451,10 @@ public class AtlasEntityType extends AtlasStructType {
return ownedRefAttributes; return ownedRefAttributes;
} }
public String getDisplayTextAttribute() {
return displayTextAttribute;
}
public List<AtlasAttribute> getDynEvalAttributes() { return dynAttributes; } public List<AtlasAttribute> getDynEvalAttributes() { return dynAttributes; }
@VisibleForTesting @VisibleForTesting
......
...@@ -26,6 +26,7 @@ import org.testng.annotations.Test; ...@@ -26,6 +26,7 @@ import org.testng.annotations.Test;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
...@@ -219,7 +220,7 @@ public class TestAtlasTypeRegistry { ...@@ -219,7 +220,7 @@ public class TestAtlasTypeRegistry {
} }
/* /*
* L0 * L0 L0_1
* / \ * / \
* / \ * / \
* L1_1---- L1_2 * L1_1---- L1_2
...@@ -230,6 +231,7 @@ public class TestAtlasTypeRegistry { ...@@ -230,6 +231,7 @@ public class TestAtlasTypeRegistry {
@Test @Test
public void testEntityDefValidHierarchy() throws AtlasBaseException { public void testEntityDefValidHierarchy() throws AtlasBaseException {
AtlasEntityDef entL0 = new AtlasEntityDef("L0"); AtlasEntityDef entL0 = new AtlasEntityDef("L0");
AtlasEntityDef entL0_1 = new AtlasEntityDef("L0-1");
AtlasEntityDef entL1_1 = new AtlasEntityDef("L1-1"); AtlasEntityDef entL1_1 = new AtlasEntityDef("L1-1");
AtlasEntityDef entL1_2 = new AtlasEntityDef("L1-2"); AtlasEntityDef entL1_2 = new AtlasEntityDef("L1-2");
AtlasEntityDef entL2_1 = new AtlasEntityDef("L2-1"); AtlasEntityDef entL2_1 = new AtlasEntityDef("L2-1");
...@@ -253,9 +255,16 @@ public class TestAtlasTypeRegistry { ...@@ -253,9 +255,16 @@ public class TestAtlasTypeRegistry {
entL2_3.addAttribute(new AtlasAttributeDef("L2-3_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); entL2_3.addAttribute(new AtlasAttributeDef("L2-3_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT));
entL2_4.addAttribute(new AtlasAttributeDef("L2-4_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(); AtlasTypesDef typesDef = new AtlasTypesDef();
typesDef.getEntityDefs().add(entL0); typesDef.getEntityDefs().add(entL0);
typesDef.getEntityDefs().add(entL0_1);
typesDef.getEntityDefs().add(entL1_1); typesDef.getEntityDefs().add(entL1_1);
typesDef.getEntityDefs().add(entL1_2); typesDef.getEntityDefs().add(entL1_2);
typesDef.getEntityDefs().add(entL2_1); typesDef.getEntityDefs().add(entL2_1);
...@@ -312,6 +321,15 @@ public class TestAtlasTypeRegistry { ...@@ -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-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-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"))); 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 @Test
...@@ -678,4 +696,16 @@ public class TestAtlasTypeRegistry { ...@@ -678,4 +696,16 @@ public class TestAtlasTypeRegistry {
assertNotNull(attributes); assertNotNull(attributes);
assertEquals(attributes.keySet(), attributeNames); 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);
}
}
} }
...@@ -704,8 +704,7 @@ public class EntityGraphRetriever { ...@@ -704,8 +704,7 @@ public class EntityGraphRetriever {
} }
} }
Object name = ret.getAttribute(NAME); Object displayText = getDisplayText(entityVertex, entityType);
Object displayText = name != null ? name : ret.getAttribute(QUALIFIED_NAME);
if (displayText != null) { if (displayText != null) {
ret.setDisplayText(displayText.toString()); ret.setDisplayText(displayText.toString());
...@@ -1484,20 +1483,31 @@ public class EntityGraphRetriever { ...@@ -1484,20 +1483,31 @@ public class EntityGraphRetriever {
} }
private Object getDisplayText(AtlasVertex entityVertex, String entityTypeName) throws AtlasBaseException { private Object getDisplayText(AtlasVertex entityVertex, String entityTypeName) throws AtlasBaseException {
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entityTypeName); return getDisplayText(entityVertex, typeRegistry.getEntityTypeByName(entityTypeName));
}
private Object getDisplayText(AtlasVertex entityVertex, AtlasEntityType entityType) throws AtlasBaseException {
Object ret = null; Object ret = null;
if (entityType != null) { if (entityType != null) {
String displayTextAttribute = entityType.getDisplayTextAttribute();
if (displayTextAttribute != null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(displayTextAttribute));
}
if (ret == null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(NAME)); ret = getVertexAttribute(entityVertex, entityType.getAttribute(NAME));
if (ret == null) { if (ret == null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(DISPLAY_NAME)); ret = getVertexAttribute(entityVertex, entityType.getAttribute(DISPLAY_NAME));
}
if (ret == null) { if (ret == null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME)); ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME));
} }
} }
}
}
return ret; return ret;
} }
......
...@@ -278,6 +278,8 @@ public class QuickStartV2 { ...@@ -278,6 +278,8 @@ public class QuickStartV2 {
createRequiredAttrDef("queryId", "string"), createRequiredAttrDef("queryId", "string"),
createRequiredAttrDef("queryGraph", "string")); createRequiredAttrDef("queryGraph", "string"));
processExecutionTypeDef.setOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE, "queryText");
AtlasEntityDef viewTypeDef = createClassTypeDef(VIEW_TYPE, VIEW_TYPE, VERSION_1, Collections.singleton("DataSet")); AtlasEntityDef viewTypeDef = createClassTypeDef(VIEW_TYPE, VIEW_TYPE, VERSION_1, Collections.singleton("DataSet"));
// Relationship-Definitions // Relationship-Definitions
......
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