ATLAS-1761: improve attribute search to enable search based on display text

Signed-off-by: Madhan Neethiraj <madhan@apache.org>
diff --git a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
index f3f6ee2..874487c 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
@@ -64,6 +64,7 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -199,34 +200,53 @@
             ret.setClassification(classification);
         }
 
-        boolean isAttributeSearch = StringUtils.isNotEmpty(attrName) && StringUtils.isNotEmpty(attrValuePrefix);
+        boolean isAttributeSearch  = StringUtils.isNotEmpty(attrName) || StringUtils.isNotEmpty(attrValuePrefix);
+        boolean isGuidPrefixSearch = false;
 
         if (isAttributeSearch) {
+            AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);
+
+            ret.setQueryType(AtlasQueryType.ATTRIBUTE);
+
+            if (entityType != null) {
+                AtlasAttribute attribute = null;
+
+                if (StringUtils.isNotEmpty(attrName)) {
+                    attribute = entityType.getAttribute(attrName);
+
+                    if (attribute == null) {
+                        throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attrName, typeName);
+                    }
+                    
+                } else {
+                    // if attrName is null|empty iterate defaultAttrNames to get attribute value
+                    final List<String> defaultAttrNames = new ArrayList<>(Arrays.asList("qualifiedName", "name"));
+                    Iterator<String>   iter             = defaultAttrNames.iterator();
+
+                    while (iter.hasNext() && attribute == null) {
+                        attrName  = iter.next();
+                        attribute = entityType.getAttribute(attrName);
+                    }
+                }
+
+                if (attribute == null) {
+                    // for guid prefix search use gremlin and nullify query to avoid using fulltext
+                    // (guids cannot be searched in fulltext)
+                    isGuidPrefixSearch = true;
+                    query              = null;
+
+                } else {
+                    attrQualifiedName = attribute.getQualifiedName();
+
+                    String  attrQuery = String.format("%s AND (%s *)", attrName, attrValuePrefix.replaceAll("\\.", " "));
+
+                    query = StringUtils.isEmpty(query) ? attrQuery : String.format("(%s) AND (%s)", query, attrQuery);
+                }
+            }
+
             if (LOG.isDebugEnabled()) {
                 LOG.debug("Executing attribute search attrName: {} and attrValue: {}", attrName, attrValuePrefix);
             }
-
-            AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);
-
-            if (entityType != null) {
-                AtlasAttribute attribute = entityType.getAttribute(attrName);
-
-                if (attribute == null) {
-                    throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attrName, typeName);
-                }
-
-                attrQualifiedName = entityType.getAttribute(attrName).getQualifiedName();
-            }
-
-            String attrQuery = String.format("%s AND (%s *)", attrName, attrValuePrefix.replaceAll("\\.", " "));
-
-            if (StringUtils.isEmpty(query)) {
-                query = attrQuery;
-            } else {
-                query = String.format("(%s) AND (%s)", query, attrQuery);
-            }
-
-            ret.setQueryType(AtlasQueryType.ATTRIBUTE);
         }
 
         // if query was provided, perform indexQuery and filter for typeName & classification in memory; this approach
@@ -304,6 +324,12 @@
                 basicQuery += gremlinQueryProvider.getQuery(AtlasGremlinQuery.BASIC_SEARCH_TYPE_FILTER);
             }
 
+            if (isGuidPrefixSearch) {
+                bindings.put("guid", attrValuePrefix + ".*");
+
+                basicQuery += gremlinQueryProvider.getQuery(AtlasGremlinQuery.GUID_PREFIX_FILTER);
+            }
+
             bindings.put("startIdx", params.offset());
             bindings.put("endIdx", params.offset() + params.limit());
 
diff --git a/repository/src/main/java/org/apache/atlas/util/AtlasGremlin2QueryProvider.java b/repository/src/main/java/org/apache/atlas/util/AtlasGremlin2QueryProvider.java
index d3413c2..139e7c3 100644
--- a/repository/src/main/java/org/apache/atlas/util/AtlasGremlin2QueryProvider.java
+++ b/repository/src/main/java/org/apache/atlas/util/AtlasGremlin2QueryProvider.java
@@ -71,6 +71,8 @@
                 return ".has('__traitNames', T.in, traitNames)";
             case TO_RANGE_LIST:
                 return " [startIdx..<endIdx].toList()";
+            case GUID_PREFIX_FILTER:
+                return ".filter{it.'__guid'.matches(guid)}";
         }
         // Should never reach this point
         return null;
diff --git a/repository/src/main/java/org/apache/atlas/util/AtlasGremlinQueryProvider.java b/repository/src/main/java/org/apache/atlas/util/AtlasGremlinQueryProvider.java
index 633fad0..8fb1793 100644
--- a/repository/src/main/java/org/apache/atlas/util/AtlasGremlinQueryProvider.java
+++ b/repository/src/main/java/org/apache/atlas/util/AtlasGremlinQueryProvider.java
@@ -58,6 +58,7 @@
         // Discovery Queries
         BASIC_SEARCH_TYPE_FILTER,
         BASIC_SEARCH_CLASSIFICATION_FILTER,
-        TO_RANGE_LIST
+        TO_RANGE_LIST,
+        GUID_PREFIX_FILTER
     }
 }
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java
index 81dbe25..edaf3ef 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java
@@ -199,7 +199,7 @@
                         attrValuePrefix + "," + typeName + "," + limit + "," + offset + ")");
             }
 
-            if (StringUtils.isEmpty(attrName) || StringUtils.isEmpty(attrValuePrefix)) {
+            if (StringUtils.isEmpty(attrName) && StringUtils.isEmpty(attrValuePrefix)) {
                 throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS,
                         String.format("attrName : {0}, attrValue: {1} for attribute search.", attrName, attrValuePrefix));
             }