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; } }
