Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -104,6 +105,10 @@ public List<String> get(AtlasExportRequest exportRequest, AtlasObjectId item) {
return ret;
}

if (StringUtils.isEmpty(item.getTypeName()) && MapUtils.isNotEmpty(item.getUniqueAttributes())) {
return getEntitiesForMatchTypeType(item, MATCH_TYPE_FOR_TYPE);
}

if (StringUtils.isNotEmpty(item.getTypeName()) && MapUtils.isNotEmpty(item.getUniqueAttributes())) {
ret = getEntitiesForMatchTypeUsingUniqueAttributes(item, matchType);

Expand Down Expand Up @@ -145,9 +150,16 @@ List<String> executeGremlinQuery(String query, Map<String, Object> bindings) {
}

private List<String> getEntitiesForMatchTypeUsingUniqueAttributes(AtlasObjectId item, String matchType) throws AtlasBaseException {
final String typeName = item.getTypeName();
final AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);

if (entityType == null || (CollectionUtils.isNotEmpty(entityType.getAllSubTypes()) && entityType.getSuperTypes().isEmpty())) {
LOG.info("Unique attribute lookup requested for abstract/generic type '{}'. Rerouting to general search.", typeName);

return getEntitiesForMatchTypeType(item, AtlasExportRequest.MATCH_TYPE_FOR_TYPE);
}

final String queryTemplate = getQueryTemplateForMatchType(matchType);
final String typeName = item.getTypeName();
final AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);

Set<String> ret = new HashSet<>();

Expand Down Expand Up @@ -177,15 +189,61 @@ private List<String> getEntitiesForMatchTypeUsingUniqueAttributes(AtlasObjectId
return new ArrayList<>(ret);
}

private List<String> getEntitiesForMatchTypeType(AtlasObjectId item, String matchType) {
return executeGremlinQuery(getQueryTemplateForMatchType(matchType), getBindingsForTypeName(item.getTypeName()));
private List<String> getEntitiesForMatchTypeType(AtlasObjectId item, String matchType) throws AtlasBaseException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add UTS for each usecase to cover scenarios and regression behaviour

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added UTS.

String typeName = item.getTypeName();

AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);

if (StringUtils.isNotEmpty(typeName) && entityType == null) {
throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_TYPENAME, typeName);
}

boolean isRootOrGenericSearch = StringUtils.isEmpty(typeName) || (CollectionUtils.isNotEmpty(entityType.getAllSubTypes()) && entityType.getSuperTypes().isEmpty());

if (isRootOrGenericSearch) {
LOG.info("Handling export for root or generic type: Executing generic query for all concrete entities.");

Collection<String> allConcreteEntityTypes = typeRegistry.getAllEntityDefNames();

if (CollectionUtils.isEmpty(allConcreteEntityTypes)) {
return new ArrayList<>();
}

String allForTypeQuery = getQueryTemplateForMatchType(AtlasExportRequest.MATCH_TYPE_FOR_TYPE);

HashMap<String, Object> bindings = new HashMap<>();
bindings.put(BINDING_PARAMETER_TYPENAME, new HashSet<>(allConcreteEntityTypes));

return executeGremlinQuery(allForTypeQuery, bindings);
}

return executeGremlinQuery(getQueryTemplateForMatchType(matchType), getBindingsForTypeName(typeName));
}

private HashMap<String, Object> getBindingsForTypeName(String typeName) {
private HashMap<String, Object> getBindingsForTypeName(String typeName) throws AtlasBaseException {
HashMap<String, Object> ret = new HashMap<>();
Set<String> typeNamesToQuery = new HashSet<>();

ret.put(BINDING_PARAMETER_TYPENAME, new HashSet<>(Arrays.asList(StringUtils.split(typeName, ","))));
List<String> providedTypeNames = Arrays.asList(StringUtils.split(typeName, ","));

for (String name : providedTypeNames) {
AtlasType type = typeRegistry.getType(name);

if (type instanceof AtlasEntityType) {
AtlasEntityType entityType = (AtlasEntityType) type;

typeNamesToQuery.add(entityType.getTypeName());

Set<String> subTypes = entityType.getAllSubTypes();
if (CollectionUtils.isNotEmpty(subTypes)) {
typeNamesToQuery.addAll(subTypes);
}
} else {
typeNamesToQuery.add(name);
}
}

ret.put(BINDING_PARAMETER_TYPENAME, typeNamesToQuery);
return ret;
}

Expand All @@ -211,4 +269,4 @@ private static Map<String, String> initMatchTypeQueryMap(AtlasGremlinQueryProvid

return ret;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.apache.atlas.model.impexp.AtlasExportRequest.MATCH_TYPE_FOR_TYPE;
import static org.apache.atlas.repository.impexp.StartEntityFetchByExportRequest.BINDING_PARAMETER_ATTR_NAME;
import static org.apache.atlas.repository.impexp.StartEntityFetchByExportRequest.BINDING_PARAMETER_TYPENAME;
import static org.apache.atlas.repository.impexp.StartEntityFetchByExportRequest.BINDING_PARAMTER_ATTR_VALUE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

@Guice(modules = TestModules.TestOnlyModule.class)
public class StartEntityFetchByExportRequestTest extends AtlasTestBase {
Expand Down Expand Up @@ -80,6 +83,55 @@ public void fetchTypeUniqueAttributes() {
assertEquals(startEntityFetchByExportRequestSpy.getSuppliedBindingsMap().get(BINDING_PARAMTER_ATTR_VALUE), "stocks@cl1");
}

@Test
public void fetchReferenceableUniqueAttributes() {
String exportRequestJson = "{ \"itemsToExport\": [ { \"typeName\": \"Referenceable\", \"uniqueAttributes\": {\"qualifiedName\": \"stocks@cl1\"} } ]}";
AtlasExportRequest exportRequest = AtlasType.fromJson(exportRequestJson, AtlasExportRequest.class);

startEntityFetchByExportRequestSpy.get(exportRequest);

assertEquals(startEntityFetchByExportRequestSpy.getGeneratedQuery(), startEntityFetchByExportRequestSpy.getQueryTemplateForMatchType(MATCH_TYPE_FOR_TYPE));

Object typeNameBinding = startEntityFetchByExportRequestSpy.getSuppliedBindingsMap().get(BINDING_PARAMETER_TYPENAME);
assertTrue(typeNameBinding instanceof Set);

Set<String> boundTypes = (Set<String>) typeNameBinding;
assertTrue(boundTypes.size() > 1);
assertTrue(boundTypes.contains("hive_table"));
}

@Test
public void fetchTypeExpansion() {
String exportRequestJson = "{ \"itemsToExport\": [ { \"typeName\": \"Asset\" } ], \"options\": {\"matchType\": \"forType\"} }";
AtlasExportRequest exportRequest = AtlasType.fromJson(exportRequestJson, AtlasExportRequest.class);

startEntityFetchByExportRequestSpy.get(exportRequest);

Set<String> boundTypes = (Set<String>) startEntityFetchByExportRequestSpy.getSuppliedBindingsMap().get(BINDING_PARAMETER_TYPENAME);
assertTrue(boundTypes.contains("Asset"));
assertTrue(boundTypes.contains("hive_db"));
}

@Test
public void fetchEmptyTypeUniqueAttributes() {
String exportRequestJson = "{ \"itemsToExport\": [ { \"typeName\": \"\", \"uniqueAttributes\": {\"qualifiedName\": \"stocks@cl1\"} } ]}";
AtlasExportRequest exportRequest = AtlasType.fromJson(exportRequestJson, AtlasExportRequest.class);

startEntityFetchByExportRequestSpy.get(exportRequest);

Set<String> boundTypes = (Set<String>) startEntityFetchByExportRequestSpy.getSuppliedBindingsMap().get(BINDING_PARAMETER_TYPENAME);
assertEquals(boundTypes.size(), typeRegistry.getAllEntityDefNames().size());
}

@Test
public void fetchUnknownType() {
String exportRequestJson = "{ \"itemsToExport\": [ { \"typeName\": \"InvalidType\" } ]}";
AtlasExportRequest exportRequest = AtlasType.fromJson(exportRequestJson, AtlasExportRequest.class);

List<AtlasObjectId> result = startEntityFetchByExportRequestSpy.get(exportRequest);
assertTrue(result.isEmpty());
}

@BeforeClass
void setup() throws IOException, AtlasBaseException {
super.basicSetup(typeDefStore, typeRegistry);
Expand Down Expand Up @@ -112,4 +164,4 @@ List<String> executeGremlinQuery(String query, Map<String, Object> bindings) {
return Collections.emptyList();
}
}
}
}
Loading