Commit 076d83c3 by Madhan Neethiraj

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

parent 159afa80
......@@ -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",
......
{
"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 @@
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();
......
......@@ -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
......
......@@ -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();
......@@ -100,6 +101,7 @@ public class AtlasEntityType extends AtlasStructType {
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 {
......@@ -107,6 +109,7 @@ public class AtlasEntityType extends AtlasStructType {
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
......
......@@ -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);
}
}
}
......@@ -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,20 +1483,31 @@ public class EntityGraphRetriever {
}
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;
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));
if (ret == null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(DISPLAY_NAME));
}
if (ret == null) {
ret = getVertexAttribute(entityVertex, entityType.getAttribute(QUALIFIED_NAME));
}
}
}
}
return ret;
}
......
......@@ -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
......
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