Repository: atlas
Updated Branches:
  refs/heads/master c9303742f -> cef91eb84


ATLAS-2347: fix V1 REST API for search to keep the response consistent with 
earlier version of Atlas


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/cef91eb8
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/cef91eb8
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/cef91eb8

Branch: refs/heads/master
Commit: cef91eb84e2952182e211cdd7a368411a8d313af
Parents: c930374
Author: Madhan Neethiraj <[email protected]>
Authored: Mon Jan 8 18:25:51 2018 -0800
Committer: Madhan Neethiraj <[email protected]>
Committed: Tue Jan 9 13:22:22 2018 -0800

----------------------------------------------------------------------
 .../java/org/apache/atlas/utils/AtlasJson.java  | 155 +++++++++++++
 .../v1/model/discovery/DSLSearchResult.java     | 156 +++++++++++++
 .../model/discovery/FullTextSearchResult.java   | 156 +++++++++++++
 .../atlas/discovery/EntityDiscoveryService.java |   9 +-
 .../resources/MetadataDiscoveryResource.java    | 232 +++++++++----------
 5 files changed, 576 insertions(+), 132 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/cef91eb8/intg/src/main/java/org/apache/atlas/utils/AtlasJson.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/utils/AtlasJson.java 
b/intg/src/main/java/org/apache/atlas/utils/AtlasJson.java
index a82b7ba..84234d9 100644
--- a/intg/src/main/java/org/apache/atlas/utils/AtlasJson.java
+++ b/intg/src/main/java/org/apache/atlas/utils/AtlasJson.java
@@ -24,21 +24,30 @@ import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult;
 import org.apache.atlas.model.notification.EntityNotification;
 import 
org.apache.atlas.model.notification.EntityNotification.EntityNotificationType;
 import org.apache.atlas.model.notification.HookNotification;
 import 
org.apache.atlas.model.notification.HookNotification.HookNotificationType;
 import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
+import org.apache.atlas.v1.model.instance.AtlasSystemAttributes;
+import org.apache.atlas.v1.model.instance.Id;
+import org.apache.atlas.v1.model.instance.Referenceable;
 import org.apache.atlas.v1.model.instance.Struct;
 import org.apache.atlas.v1.model.notification.EntityNotificationV1;
 import org.apache.atlas.v1.model.notification.HookNotificationV1.*;
+import org.apache.commons.collections.MapUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.text.DateFormat;
 import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 
 public class AtlasJson {
@@ -50,6 +59,9 @@ public class AtlasJson {
     private static final ObjectMapper mapperV1 = new ObjectMapper()
                                             
.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
 
+    private static final ObjectMapper mapperV1Search = new ObjectMapper()
+            .configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, 
true);
+
     static {
         SimpleModule atlasSerDeModule = new SimpleModule("AtlasSerDe", new 
Version(1, 0, 0, null));
 
@@ -59,6 +71,17 @@ public class AtlasJson {
         atlasSerDeModule.addDeserializer(EntityNotification.class, new 
EntityNotificationDeserializer());
 
         mapperV1.registerModule(atlasSerDeModule);
+
+        SimpleModule searchResultV1SerDeModule = new 
SimpleModule("SearchResultV1SerDe", new Version(1, 0, 0, null));
+
+        searchResultV1SerDeModule.addSerializer(Referenceable.class, new 
V1SearchReferenceableSerializer());
+        searchResultV1SerDeModule.addSerializer(Struct.class, new 
V1SearchStructSerializer());
+        searchResultV1SerDeModule.addSerializer(Id.class, new 
V1SearchIdSerializer());
+        searchResultV1SerDeModule.addSerializer(AtlasSystemAttributes.class, 
new V1SearchSystemAttributesSerializer());
+        searchResultV1SerDeModule.addSerializer(AtlasFullTextResult.class, new 
V1SearchFullTextResultSerializer());
+        searchResultV1SerDeModule.addSerializer(Date.class, new 
DateSerializer());
+
+        mapperV1Search.registerModule(searchResultV1SerDeModule);
     }
 
     public static String toJson(Object obj) {
@@ -125,6 +148,18 @@ public class AtlasJson {
         return ret;
     }
 
+    public static String toV1SearchJson(Object obj) {
+        String ret;
+        try {
+            ret = mapperV1Search.writeValueAsString(obj);
+        }catch (IOException e){
+            LOG.error("AtlasType.toV1Json()", e);
+
+            ret = null;
+        }
+        return ret;
+    }
+
 
     public static ObjectNode createV1ObjectNode() {
         return mapperV1.createObjectNode();
@@ -268,4 +303,124 @@ public class AtlasJson {
             return ret;
         }
     }
+
+    private static final String V1_KEY_$TYPENAME          = "$typeName$";
+    private static final String V1_KEY_$ID                = "$id$";
+    private static final String V1_KEY_$SYSTEM_ATTRIBUTES = 
"$systemAttributes$";
+    private static final String V1_KEY_$TRAITS            = "$traits$";
+    private static final String V1_KEY_TYPENAME           = "typeName";
+    private static final String V1_KEY_ID                 = "id";
+    private static final String V1_KEY_GUID               = "guid";
+    private static final String V1_KEY_SCORE              = "score";
+    private static final String V1_KEY_VERSION            = "version";
+    private static final String V1_KEY_STATE              = "state";
+    private static final String V1_KEY_CREATED_BY         = "createdBy";
+    private static final String V1_KEY_MODIFIED_BY        = "modifiedBy";
+    private static final String V1_KEY_CREATED_TIME       = "createdTime";
+    private static final String V1_KEY_MODIFIED_TIME      = "modifiedTime";
+
+    static class V1SearchReferenceableSerializer extends 
JsonSerializer<Referenceable> {
+        @Override
+        public void serialize(Referenceable entity, JsonGenerator jgen, 
SerializerProvider provider) throws IOException {
+            if (entity != null) {
+                Map<String, Object> valueMap = entity.getValues() != null ? 
new HashMap<>(entity.getValues()) : new HashMap<>();
+
+                if (entity.getTypeName() != null) {
+                    valueMap.put(V1_KEY_$TYPENAME, entity.getTypeName());
+                }
+
+                if (entity.getId() != null) {
+                    valueMap.put(V1_KEY_$ID, entity.getId());
+                }
+
+                if (entity.getSystemAttributes() != null) {
+                    valueMap.put(V1_KEY_$SYSTEM_ATTRIBUTES, 
entity.getSystemAttributes());
+                }
+
+                if (MapUtils.isNotEmpty(entity.getTraits())) {
+                    valueMap.put(V1_KEY_$TRAITS, entity.getTraits());
+                }
+
+                jgen.writeObject(valueMap);
+            }
+        }
+    }
+
+    static class V1SearchStructSerializer extends JsonSerializer<Struct> {
+        @Override
+        public void serialize(Struct struct, JsonGenerator jgen, 
SerializerProvider provider) throws IOException {
+            if (struct != null) {
+                Map<String, Object> valueMap = struct.getValues() != null ? 
new HashMap<>(struct.getValues()) : new HashMap<>();
+
+                valueMap.put(V1_KEY_$TYPENAME, struct.getTypeName());
+
+                jgen.writeObject(valueMap);
+            }
+        }
+    }
+
+    static class V1SearchIdSerializer extends JsonSerializer<Id> {
+        @Override
+        public void serialize(Id id, JsonGenerator jgen, SerializerProvider 
provider) throws IOException {
+            if (id != null) {
+                Map<String, Object> valueMap = new HashMap<>();
+
+                valueMap.put(V1_KEY_ID, id._getId());
+                valueMap.put(V1_KEY_$TYPENAME, id.getTypeName());
+                valueMap.put(V1_KEY_VERSION, id.getVersion());
+
+                if (id.getState() != null) {
+                    valueMap.put(V1_KEY_STATE, id.getState().toString());
+                }
+
+                jgen.writeObject(valueMap);
+            }
+        }
+    }
+
+    static class V1SearchSystemAttributesSerializer extends 
JsonSerializer<AtlasSystemAttributes> {
+        private static final ThreadLocal<DateFormat> 
V1_SEARCH_RESULT_DATE_FORMAT = new ThreadLocal<DateFormat>() {
+            @Override
+            public DateFormat initialValue() {
+                DateFormat ret = new SimpleDateFormat("EEE MMM dd HH:mm:ss z 
yyyy");
+
+                return ret;
+            }
+        };
+
+        @Override
+        public void serialize(AtlasSystemAttributes systemAttributes, 
JsonGenerator jgen, SerializerProvider provider) throws IOException {
+            if (systemAttributes != null) {
+                Map<String, Object> valueMap = new HashMap<>();
+
+                valueMap.put(V1_KEY_CREATED_BY, 
systemAttributes.getCreatedBy());
+                valueMap.put(V1_KEY_MODIFIED_BY, 
systemAttributes.getModifiedBy());
+
+                if (systemAttributes.getCreatedTime() != null) {
+                    valueMap.put(V1_KEY_CREATED_TIME, 
V1_SEARCH_RESULT_DATE_FORMAT.get().format(systemAttributes.getCreatedTime()));
+                }
+
+                if (systemAttributes.getModifiedTime() != null) {
+                    valueMap.put(V1_KEY_MODIFIED_TIME, 
V1_SEARCH_RESULT_DATE_FORMAT.get().format(systemAttributes.getModifiedTime()));
+                }
+
+                jgen.writeObject(valueMap);
+            }
+        }
+    }
+
+    static class V1SearchFullTextResultSerializer extends 
JsonSerializer<AtlasFullTextResult> {
+        @Override
+        public void serialize(AtlasFullTextResult result, JsonGenerator jgen, 
SerializerProvider provider) throws IOException {
+            if (result != null && result.getEntity() != null) {
+                Map<String, Object> valueMap = new HashMap<>();
+
+                valueMap.put(V1_KEY_GUID, result.getEntity().getGuid());
+                valueMap.put(V1_KEY_TYPENAME, 
result.getEntity().getTypeName());
+                valueMap.put(V1_KEY_SCORE, result.getScore());
+
+                jgen.writeObject(valueMap);
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/cef91eb8/intg/src/main/java/org/apache/atlas/v1/model/discovery/DSLSearchResult.java
----------------------------------------------------------------------
diff --git 
a/intg/src/main/java/org/apache/atlas/v1/model/discovery/DSLSearchResult.java 
b/intg/src/main/java/org/apache/atlas/v1/model/discovery/DSLSearchResult.java
new file mode 100644
index 0000000..2181fca
--- /dev/null
+++ 
b/intg/src/main/java/org/apache/atlas/v1/model/discovery/DSLSearchResult.java
@@ -0,0 +1,156 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.atlas.v1.model.discovery;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.apache.atlas.v1.model.instance.Referenceable;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.*;
+
+import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
+import static 
com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY;
+
+@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, 
fieldVisibility=NONE)
+@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS)
+@JsonIgnoreProperties(ignoreUnknown=true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class DSLSearchResult implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String              requestId;
+    private String              queryType;
+    private String              query;
+    private String              dataType;
+    private int                 count = 0;
+    private List<Referenceable> results;
+
+
+    public DSLSearchResult() {
+    }
+
+    public String getRequestId() {
+        return requestId;
+    }
+
+    public void setRequestId(String requestId) {
+        this.requestId = requestId;
+    }
+
+    public String getQueryType() {
+        return queryType;
+    }
+
+    public void setQueryType(String queryType) {
+        this.queryType = queryType;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    public void setQuery(String query) {
+        this.query = query;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public List<Referenceable> getResults() {
+        return results;
+    }
+
+    public void setResults(List<Referenceable> results) {
+        this.results = results;
+    }
+
+    public void addResult(Referenceable entity) {
+        if (this.results == null) {
+            this.results = new ArrayList<>();
+        }
+
+        this.results.add(entity);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        DSLSearchResult obj = (DSLSearchResult) o;
+
+        return Objects.equals(requestId, obj.requestId) &&
+               Objects.equals(queryType, obj.queryType) &&
+               Objects.equals(query, obj.query) &&
+               Objects.equals(dataType, obj.dataType) &&
+               Objects.equals(count, obj.count) &&
+               Objects.equals(results, obj.results);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(requestId, queryType, query, dataType, count, 
results);
+    }
+
+
+    @Override
+    public String toString() {
+        return toString(new StringBuilder()).toString();
+    }
+
+    public StringBuilder toString(StringBuilder sb) {
+        if (sb == null) {
+            sb = new StringBuilder();
+        }
+
+        sb.append("FullTextSearchResult{")
+                .append("requestId=").append(requestId)
+                .append(", queryType=").append(queryType)
+                .append(", query=").append(query)
+                .append(", dataType=").append(dataType)
+                .append(", count=").append(count)
+                .append(", results=").append(results)
+                .append("}");
+
+        return sb;
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/cef91eb8/intg/src/main/java/org/apache/atlas/v1/model/discovery/FullTextSearchResult.java
----------------------------------------------------------------------
diff --git 
a/intg/src/main/java/org/apache/atlas/v1/model/discovery/FullTextSearchResult.java
 
b/intg/src/main/java/org/apache/atlas/v1/model/discovery/FullTextSearchResult.java
new file mode 100644
index 0000000..b115948
--- /dev/null
+++ 
b/intg/src/main/java/org/apache/atlas/v1/model/discovery/FullTextSearchResult.java
@@ -0,0 +1,156 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.atlas.v1.model.discovery;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.*;
+
+import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
+import static 
com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY;
+
+@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, 
fieldVisibility=NONE)
+@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS)
+@JsonIgnoreProperties(ignoreUnknown=true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class FullTextSearchResult implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String                    requestId;
+    private String                    queryType;
+    private String                    query;
+    private String                    dataType;
+    private int                       count = 0;
+    private List<AtlasFullTextResult> results;
+
+
+    public FullTextSearchResult() {
+    }
+
+    public String getRequestId() {
+        return requestId;
+    }
+
+    public void setRequestId(String requestId) {
+        this.requestId = requestId;
+    }
+
+    public String getQueryType() {
+        return queryType;
+    }
+
+    public void setQueryType(String queryType) {
+        this.queryType = queryType;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    public void setQuery(String query) {
+        this.query = query;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public List<AtlasFullTextResult> getResults() {
+        return results;
+    }
+
+    public void setResults(List<AtlasFullTextResult> results) {
+        this.results = results;
+    }
+
+    public void addResult(AtlasFullTextResult result) {
+        if (this.results == null) {
+            this.results = new ArrayList<>();
+        }
+
+        this.results.add(result);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        FullTextSearchResult obj = (FullTextSearchResult) o;
+
+        return Objects.equals(requestId, obj.requestId) &&
+               Objects.equals(queryType, obj.queryType) &&
+               Objects.equals(query, obj.query) &&
+               Objects.equals(dataType, obj.dataType) &&
+               Objects.equals(count, obj.count) &&
+               Objects.equals(results, obj.results);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(requestId, queryType, query, dataType, count, 
results);
+    }
+
+
+    @Override
+    public String toString() {
+        return toString(new StringBuilder()).toString();
+    }
+
+    public StringBuilder toString(StringBuilder sb) {
+        if (sb == null) {
+            sb = new StringBuilder();
+        }
+
+        sb.append("FullTextSearchResult{")
+                .append("requestId=").append(requestId)
+                .append(", queryType=").append(queryType)
+                .append(", query=").append(query)
+                .append(", dataType=").append(dataType)
+                .append(", count=").append(count)
+                .append(", results=").append(results)
+                .append("}");
+
+        return sb;
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/cef91eb8/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
----------------------------------------------------------------------
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 29b2abe..ab69fe7 100644
--- 
a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
+++ 
b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
@@ -117,14 +117,15 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
     @Override
     @GraphTransaction
     public AtlasSearchResult searchUsingDslQuery(String dslQuery, int limit, 
int offset) throws AtlasBaseException {
-        AtlasSearchResult ret = new AtlasSearchResult(dslQuery, 
AtlasQueryType.DSL);
-        GremlinQuery gremlinQuery = toGremlinQuery(dslQuery, limit, offset);
+        AtlasSearchResult ret          = new AtlasSearchResult(dslQuery, 
AtlasQueryType.DSL);
+        GremlinQuery      gremlinQuery = toGremlinQuery(dslQuery, limit, 
offset);
+        String            queryStr     = gremlinQuery.queryStr();
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("Executing DSL query: {}", dslQuery);
+            LOG.debug("Executing DSL: query={}, gremlinQuery={}", dslQuery, 
queryStr);
         }
 
-        Object result = graph.executeGremlinScript(gremlinQuery.queryStr(), 
false);
+        Object result = graph.executeGremlinScript(queryStr, false);
 
         if (result instanceof List && 
CollectionUtils.isNotEmpty((List)result)) {
             List   queryResult  = (List) result;

http://git-wip-us.apache.org/repos/asf/atlas/blob/cef91eb8/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
----------------------------------------------------------------------
diff --git 
a/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
 
b/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
index 252cc0e..34ba4da 100755
--- 
a/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
+++ 
b/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
@@ -18,21 +18,23 @@
 
 package org.apache.atlas.web.resources;
 
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.base.Preconditions;
-import org.apache.atlas.AtlasClient;
 import org.apache.atlas.AtlasConfiguration;
 import org.apache.atlas.discovery.AtlasDiscoveryService;
+import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.discovery.AtlasSearchResult;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
 import org.apache.atlas.query.QueryParams;
-import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.repository.converters.AtlasInstanceConverter;
+import org.apache.atlas.repository.store.graph.AtlasEntityStore;
 import org.apache.atlas.utils.AtlasJson;
 import org.apache.atlas.utils.AtlasPerfTracer;
 import org.apache.atlas.utils.ParamChecker;
+import org.apache.atlas.v1.model.discovery.DSLSearchResult;
+import org.apache.atlas.v1.model.discovery.FullTextSearchResult;
+import org.apache.atlas.v1.model.instance.Referenceable;
 import org.apache.atlas.web.util.Servlets;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.collections.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -47,7 +49,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
-import java.io.IOException;
+import java.util.List;
 
 /**
  * Jersey Resource for metadata operations.
@@ -64,17 +66,23 @@ public class MetadataDiscoveryResource {
     private static final String QUERY_TYPE_FULLTEXT = "full-text";
     private static final String LIMIT_OFFSET_DEFAULT = "-1";
 
-    private final AtlasDiscoveryService atlasDiscoveryService;
+    private final AtlasDiscoveryService  atlasDiscoveryService;
+    private final AtlasInstanceConverter restAdapters;
+    private final AtlasEntityStore       entitiesStore;
 
     /**
      * Created by the Guice ServletModule and injected with the
      * configured DiscoveryService.
      *
-     * @param configuration configuration
+     * @param atlasDiscoveryService atlasDiscoveryService
+     * @param restAdapters restAdapters
+     * @param entitiesStore entitiesStore
      */
     @Inject
-    public MetadataDiscoveryResource(AtlasDiscoveryService 
atlasDiscoveryService, Configuration configuration) {
+    public MetadataDiscoveryResource(AtlasDiscoveryService 
atlasDiscoveryService, AtlasInstanceConverter restAdapters, AtlasEntityStore 
entitiesStore) {
         this.atlasDiscoveryService = atlasDiscoveryService;
+        this.restAdapters          = restAdapters;
+        this.entitiesStore         = entitiesStore;
     }
 
     /**
@@ -144,11 +152,53 @@ public class MetadataDiscoveryResource {
             }
 
             dslQuery = ParamChecker.notEmpty(dslQuery, "dslQuery cannot be 
null");
-            QueryParams queryParams = validateQueryParams(limit, offset);
-            AtlasSearchResult result = 
atlasDiscoveryService.searchUsingDslQuery(dslQuery, queryParams.limit(), 
queryParams.offset());
-            final String jsonResultStr = result.getEntities() == null ? null : 
AtlasType.toJson(result.getEntities());
 
-            ObjectNode response = new 
DSLJSONResponseBuilder().results(jsonResultStr).query(dslQuery).build();
+            QueryParams       queryParams = validateQueryParams(limit, offset);
+            AtlasSearchResult result      = 
atlasDiscoveryService.searchUsingDslQuery(dslQuery, queryParams.limit(), 
queryParams.offset());
+            DSLSearchResult   dslResult   = new DSLSearchResult();
+
+            dslResult.setQueryType(QUERY_TYPE_DSL);
+            dslResult.setRequestId(Servlets.getRequestId());
+            dslResult.setDataType(result.getType());
+            dslResult.setQuery(result.getQueryText());
+            dslResult.setCount(0);
+
+            if (CollectionUtils.isNotEmpty(result.getEntities())) {
+                for (AtlasEntityHeader entityHeader : result.getEntities()) {
+                    Referenceable entity = getEntity(entityHeader.getGuid());
+
+                    dslResult.addResult(entity);
+                }
+
+                if (dslResult.getResults() != null) {
+                    dslResult.setCount(dslResult.getResults().size());
+                }
+            } else if (result.getAttributes() != null && 
CollectionUtils.isNotEmpty(result.getAttributes().getName())) {
+                List<String> attrNames = result.getAttributes().getName();
+
+                for (List<Object> attrValues : 
result.getAttributes().getValues()) {
+                    if (attrValues == null) {
+                        continue;
+                    }
+
+                    Referenceable entity = new Referenceable();
+
+                    for (int i = 0; i < attrNames.size(); i++) {
+                        String attrName  = attrNames.get(i);
+                        Object attrValue = attrValues.size() > i ? 
attrValues.get(i) : null;
+
+                        entity.set(attrName, attrValue);
+                    }
+
+                    dslResult.addResult(entity);
+                }
+
+                if (dslResult.getResults() != null) {
+                    dslResult.setCount(dslResult.getResults().size());
+                }
+            }
+
+            String response = AtlasJson.toV1SearchJson(dslResult);
 
             return Response.ok(response).build();
         } catch (IllegalArgumentException e) {
@@ -169,28 +219,6 @@ public class MetadataDiscoveryResource {
         }
     }
 
-    private QueryParams validateQueryParams(int limitParam, int offsetParam) {
-        int maxLimit = AtlasConfiguration.SEARCH_MAX_LIMIT.getInt();
-        int defaultLimit = AtlasConfiguration.SEARCH_DEFAULT_LIMIT.getInt();
-
-        int limit = defaultLimit;
-        boolean limitSet = (limitParam != 
Integer.valueOf(LIMIT_OFFSET_DEFAULT));
-        if (limitSet) {
-            ParamChecker.lessThan(limitParam, maxLimit, "limit");
-            ParamChecker.greaterThan(limitParam, 0, "limit");
-            limit = limitParam;
-        }
-
-        int offset = 0;
-        boolean offsetSet = (offsetParam != 
Integer.valueOf(LIMIT_OFFSET_DEFAULT));
-        if (offsetSet) {
-            ParamChecker.greaterThan(offsetParam, -1, "offset");
-            offset = offsetParam;
-        }
-
-        return new QueryParams(limit, offset);
-    }
-
     /**
      * Search using full text search.
      *
@@ -217,11 +245,27 @@ public class MetadataDiscoveryResource {
             }
 
             query = ParamChecker.notEmpty(query, "query cannot be null or 
empty");
-            QueryParams queryParams = validateQueryParams(limit, offset);
-            AtlasSearchResult result = 
atlasDiscoveryService.searchUsingFullTextQuery(query, false, 
queryParams.limit(), queryParams.offset());
-            final String jsonResultStr = result.getFullTextResult() == null ? 
null : AtlasType.toJson(result.getFullTextResult());
 
-            ObjectNode response = new 
FullTextJSonResponseBuilder().results(jsonResultStr).query(query).build();
+            QueryParams          queryParams    = validateQueryParams(limit, 
offset);
+            AtlasSearchResult    result         = 
atlasDiscoveryService.searchUsingFullTextQuery(query, false, 
queryParams.limit(), queryParams.offset());
+            FullTextSearchResult fullTextResult = new FullTextSearchResult();
+
+            fullTextResult.setQueryType(QUERY_TYPE_FULLTEXT);
+            fullTextResult.setRequestId(Servlets.getRequestId());
+            fullTextResult.setDataType(result.getType());
+            fullTextResult.setQuery(result.getQueryText());
+            fullTextResult.setCount(0);
+
+            if (CollectionUtils.isNotEmpty(result.getFullTextResult())) {
+                for (AtlasSearchResult.AtlasFullTextResult entity : 
result.getFullTextResult()) {
+                    fullTextResult.addResult(entity);
+                }
+
+                fullTextResult.setCount(fullTextResult.getResults().size());
+            }
+
+            String response = AtlasJson.toV1SearchJson(fullTextResult);
+
             return Response.ok(response).build();
         } catch (IllegalArgumentException e) {
             LOG.error("Unable to get entity list for query {}", query, e);
@@ -241,102 +285,34 @@ public class MetadataDiscoveryResource {
         }
     }
 
-    private class JsonResponseBuilder {
-
-        protected int count = 0;
-        protected String query;
-        protected String queryType;
-        protected ObjectNode response;
-
-        JsonResponseBuilder() {
-            this.response = AtlasJson.createV1ObjectNode();
-        }
-
-        protected JsonResponseBuilder count(int count) {
-            this.count = count;
-            return this;
-        }
-
-        public JsonResponseBuilder query(String query) {
-            this.query = query;
-            return this;
-        }
-
-        public JsonResponseBuilder queryType(String queryType) {
-            this.queryType = queryType;
-            return this;
-        }
-
-        protected ObjectNode build() {
-
-            Preconditions.checkNotNull(query, "Query cannot be null");
-            Preconditions.checkNotNull(queryType, "Query Type must be 
specified");
-            Preconditions.checkArgument(count >= 0, "Search Result count 
should be > 0");
-
-            response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId());
-            response.put(AtlasClient.QUERY, query);
-            response.put(AtlasClient.QUERY_TYPE, queryType);
-            response.put(AtlasClient.COUNT, count);
-            return response;
-        }
-    }
-
-    private class DSLJSONResponseBuilder extends JsonResponseBuilder {
-
-        DSLJSONResponseBuilder() {
-            super();
-        }
+    private QueryParams validateQueryParams(int limitParam, int offsetParam) {
+        int     maxLimit     = AtlasConfiguration.SEARCH_MAX_LIMIT.getInt();
+        int     defaultLimit = 
AtlasConfiguration.SEARCH_DEFAULT_LIMIT.getInt();
+        int     limit        = defaultLimit;
+        boolean limitSet     = (limitParam != 
Integer.valueOf(LIMIT_OFFSET_DEFAULT));
 
-        private ArrayNode dslResults;
+        if (limitSet) {
+            ParamChecker.lessThan(limitParam, maxLimit, "limit");
+            ParamChecker.greaterThan(limitParam, 0, "limit");
 
-        public DSLJSONResponseBuilder results(ArrayNode dslResults) {
-            this.dslResults = dslResults;
-            return this;
+            limit = limitParam;
         }
 
-        public DSLJSONResponseBuilder results(String dslResults) throws 
IOException {
-            return results(StringUtils.isEmpty(dslResults) ? 
AtlasJson.createV1ArrayNode() : AtlasJson.parseToV1ArrayNode(dslResults));
-        }
+        int     offset    = 0;
+        boolean offsetSet = (offsetParam != 
Integer.valueOf(LIMIT_OFFSET_DEFAULT));
 
-        @Override
-        public ObjectNode build()  {
-            Preconditions.checkNotNull(dslResults);
-            count(dslResults.size());
-            queryType(QUERY_TYPE_DSL);
-            ObjectNode response = super.build();
-            response.putPOJO(AtlasClient.RESULTS, dslResults);
-            response.put(AtlasClient.DATATYPE, 
dslResults.get(AtlasClient.DATATYPE));
-            return response;
+        if (offsetSet) {
+            ParamChecker.greaterThan(offsetParam, -1, "offset");
+            offset = offsetParam;
         }
 
+        return new QueryParams(limit, offset);
     }
 
-    private class FullTextJSonResponseBuilder extends JsonResponseBuilder {
+    private Referenceable getEntity(String guid) throws AtlasBaseException {
+        AtlasEntityWithExtInfo entity        = entitiesStore.getById(guid);
+        Referenceable          referenceable = 
restAdapters.getReferenceable(entity);
 
-        private ArrayNode fullTextResults;
-
-        public FullTextJSonResponseBuilder results(ArrayNode fullTextResults) {
-            this.fullTextResults = fullTextResults;
-            return this;
-        }
-
-        public FullTextJSonResponseBuilder results(String dslResults) throws 
IOException {
-            return results(StringUtils.isEmpty(dslResults) ? 
AtlasJson.createV1ArrayNode() : AtlasJson.parseToV1ArrayNode(dslResults));
-        }
-
-        public FullTextJSonResponseBuilder() {
-            super();
-        }
-
-        @Override
-        public ObjectNode build() {
-            Preconditions.checkNotNull(fullTextResults);
-            count(fullTextResults.size());
-            queryType(QUERY_TYPE_FULLTEXT);
-
-            ObjectNode response = super.build();
-            response.put(AtlasClient.RESULTS, fullTextResults);
-            return response;
-        }
+        return referenceable;
     }
 }

Reply via email to