Commit 7da5e03f by Venkatesh Seetharam

ISSUE-39 Add typed instance list end to end. Contributed by Venkatesh Seetharam

parent be7c4cb6
...@@ -23,6 +23,7 @@ import com.thinkaurelius.titan.core.TitanVertex; ...@@ -23,6 +23,7 @@ import com.thinkaurelius.titan.core.TitanVertex;
import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Graph; import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.GraphQuery;
import com.tinkerpop.blueprints.TransactionalGraph; import com.tinkerpop.blueprints.TransactionalGraph;
import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.blueprints.Vertex;
import org.apache.commons.collections.map.HashedMap; import org.apache.commons.collections.map.HashedMap;
...@@ -58,6 +59,7 @@ import java.math.BigInteger; ...@@ -58,6 +59,7 @@ import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
...@@ -160,6 +162,27 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -160,6 +162,27 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
} }
} }
@Override
public List<String> getEntityList(String entityType) throws RepositoryException {
LOG.info("Retrieving entity list for type={}", entityType);
GraphQuery query = graphService.getBlueprintsGraph().query()
.has(Constants.ENTITY_TYPE_PROPERTY_KEY, entityType);
Iterator<Vertex> results = query.vertices().iterator();
if (!results.hasNext()) {
return Collections.emptyList();
}
ArrayList<String> entityList = new ArrayList<>();
while (results.hasNext()) {
Vertex vertex = results.next();
entityList.add(vertex.<String>getProperty(Constants.GUID_PROPERTY_KEY));
}
return entityList;
}
@Override
public List<Map<String,String>> rawSearch(String gremlinQuery) throws RepositoryException { public List<Map<String,String>> rawSearch(String gremlinQuery) throws RepositoryException {
ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("gremlin-groovy"); ScriptEngine engine = manager.getEngineByName("gremlin-groovy");
...@@ -209,12 +232,6 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -209,12 +232,6 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
} }
} }
@Override
public List<String> getEntityList(String entityType) throws RepositoryException {
LOG.info("Retrieving entity list for type={}", entityType);
return Collections.emptyList();
}
private final class EntityProcessor implements ObjectGraphWalker.NodeProcessor { private final class EntityProcessor implements ObjectGraphWalker.NodeProcessor {
public final Map<Id, Id> idToNewIdMap; public final Map<Id, Id> idToNewIdMap;
...@@ -328,7 +345,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -328,7 +345,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
throws MetadataException { throws MetadataException {
String typedInstanceGUID = null; String typedInstanceGUID = null;
for (ITypedReferenceableInstance typedInstance : newTypedInstances) { // Traverse over newInstances for (ITypedReferenceableInstance typedInstance : newTypedInstances) { // Traverse over newInstances
LOG.debug("Adding typed instance {}", typedInstance); LOG.debug("Adding typed instance {}", typedInstance.getTypeName());
Id id = typedInstance.getId(); Id id = typedInstance.getId();
if (id == null) { // oops if (id == null) { // oops
...@@ -364,7 +381,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -364,7 +381,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
Map<String, AttributeInfo> fields, Map<String, AttributeInfo> fields,
Map<Id, Vertex> idToVertexMap) throws MetadataException { Map<Id, Vertex> idToVertexMap) throws MetadataException {
LOG.debug("Mapping instance {} to vertex {} for fields {}", LOG.debug("Mapping instance {} to vertex {} for fields {}",
typedInstance, instanceVertex, fields); typedInstance.getTypeName(), instanceVertex, fields);
for (AttributeInfo attributeInfo : fields.values()) { for (AttributeInfo attributeInfo : fields.values()) {
LOG.debug("mapping attributeInfo {}", attributeInfo); LOG.debug("mapping attributeInfo {}", attributeInfo);
final IDataType dataType = attributeInfo.dataType(); final IDataType dataType = attributeInfo.dataType();
...@@ -611,7 +628,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -611,7 +628,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
private void mapVertexToStructInstance(Vertex instanceVertex, private void mapVertexToStructInstance(Vertex instanceVertex,
ITypedInstance typedInstance, ITypedInstance typedInstance,
AttributeInfo attributeInfo) throws MetadataException { AttributeInfo attributeInfo) throws MetadataException {
LOG.debug("mapping vertex {} to struct {}", typedInstance, attributeInfo.name); LOG.debug("mapping vertex {} to struct {}", instanceVertex, attributeInfo.name);
StructType structType = typeSystem.getDataType( StructType structType = typeSystem.getDataType(
StructType.class, attributeInfo.dataType().getName()); StructType.class, attributeInfo.dataType().getName());
ITypedStruct structInstance = structType.createInstance(); ITypedStruct structInstance = structType.createInstance();
......
...@@ -27,11 +27,11 @@ import org.apache.hadoop.metadata.json.TypesSerialization; ...@@ -27,11 +27,11 @@ import org.apache.hadoop.metadata.json.TypesSerialization;
import org.apache.hadoop.metadata.listener.TypedInstanceChangeListener; import org.apache.hadoop.metadata.listener.TypedInstanceChangeListener;
import org.apache.hadoop.metadata.listener.TypesChangeListener; import org.apache.hadoop.metadata.listener.TypesChangeListener;
import org.apache.hadoop.metadata.repository.MetadataRepository; import org.apache.hadoop.metadata.repository.MetadataRepository;
import org.apache.hadoop.metadata.storage.RepositoryException;
import org.apache.hadoop.metadata.types.IDataType; import org.apache.hadoop.metadata.types.IDataType;
import org.apache.hadoop.metadata.types.TypeSystem; import org.apache.hadoop.metadata.types.TypeSystem;
import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException; import org.json.simple.parser.ParseException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -73,7 +73,7 @@ public class DefaultMetadataService implements MetadataService { ...@@ -73,7 +73,7 @@ public class DefaultMetadataService implements MetadataService {
public JSONObject createType(String typeName, public JSONObject createType(String typeName,
String typeDefinition) throws MetadataException { String typeDefinition) throws MetadataException {
try { try {
validate(typeName, typeDefinition); validateTypeDoesNotExist(typeName, typeDefinition);
TypesDef typesDef = TypesSerialization.fromJson(typeDefinition); TypesDef typesDef = TypesSerialization.fromJson(typeDefinition);
Map<String, IDataType> typesAdded = typeSystem.defineTypes(typesDef); Map<String, IDataType> typesAdded = typeSystem.defineTypes(typesDef);
...@@ -86,20 +86,16 @@ public class DefaultMetadataService implements MetadataService { ...@@ -86,20 +86,16 @@ public class DefaultMetadataService implements MetadataService {
} }
return response; return response;
} catch (ParseException e) {
LOG.error("Unable to parse JSON for type {}", typeName, e);
throw new MetadataException("validation failed for: " + typeName);
} catch (JSONException e) { } catch (JSONException e) {
LOG.error("Unable to persist type {}", typeName, e); LOG.error("Unable to persist type {}", typeName, e);
throw new MetadataException("Unable to create response for: " + typeName); throw new MetadataException("Unable to create response for: " + typeName);
} }
} }
private void validate(String typeName, private void validateTypeDoesNotExist(String typeName,
String typeDefinition) throws ParseException, MetadataException { String typeDefinition) throws MetadataException {
Preconditions.checkNotNull(typeName, "type name cannot be null"); Preconditions.checkNotNull(typeName, "type name cannot be null");
Preconditions.checkNotNull(typeDefinition, "type definition cannot be null"); Preconditions.checkNotNull(typeDefinition, "type definition cannot be null");
JSONValue.parseWithException(typeDefinition);
// verify if the type already exists // verify if the type already exists
String existingTypeDefinition = null; String existingTypeDefinition = null;
...@@ -110,7 +106,7 @@ public class DefaultMetadataService implements MetadataService { ...@@ -110,7 +106,7 @@ public class DefaultMetadataService implements MetadataService {
} }
if (existingTypeDefinition != null) { if (existingTypeDefinition != null) {
throw new MetadataException("type is already defined for : " + typeName); throw new RepositoryException("type is already defined for : " + typeName);
} }
} }
...@@ -178,8 +174,9 @@ public class DefaultMetadataService implements MetadataService { ...@@ -178,8 +174,9 @@ public class DefaultMetadataService implements MetadataService {
*/ */
@Override @Override
public String getEntityDefinition(String guid) throws MetadataException { public String getEntityDefinition(String guid) throws MetadataException {
final ITypedReferenceableInstance instance = Preconditions.checkNotNull(guid, "guid cannot be null");
repository.getEntityDefinition(guid);
final ITypedReferenceableInstance instance = repository.getEntityDefinition(guid);
return instance == null return instance == null
? null ? null
: Serialization$.MODULE$.toJson(instance); : Serialization$.MODULE$.toJson(instance);
...@@ -192,8 +189,26 @@ public class DefaultMetadataService implements MetadataService { ...@@ -192,8 +189,26 @@ public class DefaultMetadataService implements MetadataService {
* @return list of entity names for the given type in the repository * @return list of entity names for the given type in the repository
*/ */
@Override @Override
public List<String> getEntityNamesList(String entityType) throws MetadataException { public List<String> getEntityList(String entityType) throws MetadataException {
throw new UnsupportedOperationException(); validateTypeExists(entityType);
return repository.getEntityList(entityType);
}
private void validateTypeExists(String entityType) throws MetadataException {
Preconditions.checkNotNull(entityType, "entity type cannot be null");
// verify if the type exists
String existingTypeDefinition = null;
try {
existingTypeDefinition = getTypeDefinition(entityType);
} catch (MetadataException ignore) {
// do nothing
}
if (existingTypeDefinition == null) {
throw new RepositoryException("type is not defined for : " + entityType);
}
} }
private void onAdd(Map<String, IDataType> typesAdded) throws MetadataException { private void onAdd(Map<String, IDataType> typesAdded) throws MetadataException {
......
...@@ -78,5 +78,5 @@ public interface MetadataService extends Service { ...@@ -78,5 +78,5 @@ public interface MetadataService extends Service {
* @param entityType type * @param entityType type
* @return list of entity names for the given type in the repository * @return list of entity names for the given type in the repository
*/ */
List<String> getEntityNamesList(String entityType) throws MetadataException; List<String> getEntityList(String entityType) throws MetadataException;
} }
...@@ -19,8 +19,11 @@ ...@@ -19,8 +19,11 @@
package org.apache.hadoop.metadata.web.resources; package org.apache.hadoop.metadata.web.resources;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import org.apache.hadoop.metadata.MetadataException;
import org.apache.hadoop.metadata.services.MetadataService; import org.apache.hadoop.metadata.services.MetadataService;
import org.apache.hadoop.metadata.web.util.Servlets; import org.apache.hadoop.metadata.web.util.Servlets;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -40,6 +43,7 @@ import javax.ws.rs.WebApplicationException; ...@@ -40,6 +43,7 @@ import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.List;
/** /**
* Entity management operations as REST API. * Entity management operations as REST API.
...@@ -120,19 +124,27 @@ public class EntityResource { ...@@ -120,19 +124,27 @@ public class EntityResource {
} }
@GET @GET
@Path("definition/{entityType}/{entityName}")
@Produces(MediaType.APPLICATION_JSON)
public Response getEntityDefinition(@PathParam("entityType") String entityType,
@PathParam("entityName") String entityName) {
return Response.status(Response.Status.SERVICE_UNAVAILABLE).build();
}
@GET
@Path("list/{entityType}") @Path("list/{entityType}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response getEntityList(@PathParam("entityType") String entityType, public Response getEntityList(@PathParam("entityType") String entityType,
@DefaultValue("0") @QueryParam("offset") Integer offset, @DefaultValue("0") @QueryParam("offset") Integer offset,
@QueryParam("numResults") Integer resultsPerPage) { @QueryParam("numResults") Integer resultsPerPage) {
return Response.ok().build(); try {
final List<String> entityList = metadataService.getEntityList(entityType);
JSONObject response = new JSONObject();
response.put("requestId", Thread.currentThread().getName());
response.put("list", new JSONArray(entityList));
return Response.ok(response).build();
} catch (MetadataException e) {
LOG.error("Unable to get entity list for type {}", entityType, e);
throw new WebApplicationException(
Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
} catch (JSONException e) {
LOG.error("Unable to get entity list for type {}", entityType, e);
throw new WebApplicationException(
Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
}
} }
} }
...@@ -124,7 +124,7 @@ public class TypesResource { ...@@ -124,7 +124,7 @@ public class TypesResource {
return Response.ok(response).build(); return Response.ok(response).build();
} catch (Exception e) { } catch (Exception e) {
LOG.error("Unable to persist entity object", e); LOG.error("Unable to get types list", e);
throw new WebApplicationException( throw new WebApplicationException(
Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
} }
......
...@@ -33,6 +33,8 @@ import org.apache.hadoop.metadata.types.HierarchicalTypeDefinition; ...@@ -33,6 +33,8 @@ import org.apache.hadoop.metadata.types.HierarchicalTypeDefinition;
import org.apache.hadoop.metadata.types.Multiplicity; import org.apache.hadoop.metadata.types.Multiplicity;
import org.apache.hadoop.metadata.types.StructTypeDefinition; import org.apache.hadoop.metadata.types.StructTypeDefinition;
import org.apache.hadoop.metadata.types.TraitType; import org.apache.hadoop.metadata.types.TraitType;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -140,7 +142,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -140,7 +142,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
*/ */
@Test @Test
public void testGetInvalidEntityDefinition() { public void testGetInvalidEntityDefinition() throws Exception {
WebResource resource = service WebResource resource = service
.path("api/metadata/entities/definition") .path("api/metadata/entities/definition")
.path("blah"); .path("blah");
...@@ -150,12 +152,13 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -150,12 +152,13 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
.type(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON)
.method(HttpMethod.GET, ClientResponse.class); .method(HttpMethod.GET, ClientResponse.class);
Assert.assertEquals(clientResponse.getStatus(), Response.Status.NOT_FOUND.getStatusCode()); Assert.assertEquals(clientResponse.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
String response = clientResponse.getEntity(String.class);
System.out.println("response = " + response); String responseAsString = clientResponse.getEntity(String.class);
Assert.assertNotNull(responseAsString);
} }
@Test (dependsOnMethods = "testSubmitEntity", enabled = false) @Test (dependsOnMethods = "testSubmitEntity")
public void testGetEntityList() { public void testGetEntityList() throws Exception {
ClientResponse clientResponse = service ClientResponse clientResponse = service
.path("api/metadata/entities/list/") .path("api/metadata/entities/list/")
.path(TABLE_TYPE) .path(TABLE_TYPE)
...@@ -163,20 +166,63 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -163,20 +166,63 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
.type(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON)
.method(HttpMethod.GET, ClientResponse.class); .method(HttpMethod.GET, ClientResponse.class);
Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
String response = clientResponse.getEntity(String.class);
System.out.println("response = " + response); String responseAsString = clientResponse.getEntity(String.class);
Assert.assertNotNull(responseAsString);
JSONObject response = new JSONObject(responseAsString);
Assert.assertNotNull(response.get("requestId"));
final JSONArray list = response.getJSONArray("list");
Assert.assertNotNull(list);
Assert.assertEquals(list.length(), 1);
} }
@Test (enabled = false) // todo: enable this later @Test
public void testGetEntityListForBadEntityType() { public void testGetEntityListForBadEntityType() throws Exception {
ClientResponse clientResponse = service ClientResponse clientResponse = service
.path("api/metadata/entities/list/blah") .path("api/metadata/entities/list/blah")
.accept(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON)
.method(HttpMethod.GET, ClientResponse.class); .method(HttpMethod.GET, ClientResponse.class);
Assert.assertEquals(clientResponse.getStatus(), Response.Status.NOT_FOUND.getStatusCode()); Assert.assertEquals(clientResponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
String response = clientResponse.getEntity(String.class);
System.out.println("response = " + response); String responseAsString = clientResponse.getEntity(String.class);
Assert.assertNotNull(responseAsString);
}
@Test
public void testGetEntityListForNoInstances() throws Exception {
addNewType();
ClientResponse clientResponse = service
.path("api/metadata/entities/list/test")
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.method(HttpMethod.GET, ClientResponse.class);
Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
String responseAsString = clientResponse.getEntity(String.class);
Assert.assertNotNull(responseAsString);
JSONObject response = new JSONObject(responseAsString);
Assert.assertNotNull(response.get("requestId"));
final JSONArray list = response.getJSONArray("list");
Assert.assertEquals(list.length(), 0);
}
private void addNewType() throws Exception {
HierarchicalTypeDefinition<ClassType> testTypeDefinition =
createClassTypeDef("test",
ImmutableList.<String>of(),
createRequiredAttrDef("name", DataTypes.STRING_TYPE),
createRequiredAttrDef("description", DataTypes.STRING_TYPE));
typeSystem.defineClassType(testTypeDefinition);
String typesAsJSON = TypesSerialization.toJson(typeSystem,
Arrays.asList(new String[]{"test"}));
sumbitType(typesAsJSON, "test");
} }
private void createHiveTypes() throws Exception { private void createHiveTypes() throws Exception {
...@@ -220,10 +266,13 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -220,10 +266,13 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
private void submitTypes() throws Exception { private void submitTypes() throws Exception {
String typesAsJSON = TypesSerialization.toJson(typeSystem, String typesAsJSON = TypesSerialization.toJson(typeSystem,
Arrays.asList(new String[]{DATABASE_TYPE, TABLE_TYPE, "serdeType", "classification"})); Arrays.asList(new String[]{DATABASE_TYPE, TABLE_TYPE, "serdeType", "classification"}));
sumbitType(typesAsJSON, TABLE_TYPE);
}
private void sumbitType(String typesAsJSON, String type) throws JSONException {
WebResource resource = service WebResource resource = service
.path("api/metadata/types/submit") .path("api/metadata/types/submit")
.path(TABLE_TYPE); .path(type);
ClientResponse clientResponse = resource ClientResponse clientResponse = resource
.accept(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)
...@@ -235,12 +284,12 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -235,12 +284,12 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
Assert.assertNotNull(responseAsString); Assert.assertNotNull(responseAsString);
JSONObject response = new JSONObject(responseAsString); JSONObject response = new JSONObject(responseAsString);
Assert.assertEquals(response.get("typeName"), TABLE_TYPE); Assert.assertEquals(response.get("typeName"), type);
Assert.assertNotNull(response.get("types")); Assert.assertNotNull(response.get("types"));
Assert.assertNotNull(response.get("requestId")); Assert.assertNotNull(response.get("requestId"));
} }
protected ITypedReferenceableInstance createHiveTableInstance() throws Exception { private ITypedReferenceableInstance createHiveTableInstance() throws Exception {
Referenceable databaseInstance = new Referenceable(DATABASE_TYPE); Referenceable databaseInstance = new Referenceable(DATABASE_TYPE);
databaseInstance.set("name", DATABASE_NAME); databaseInstance.set("name", DATABASE_NAME);
databaseInstance.set("description", "foo database"); databaseInstance.set("description", "foo database");
......
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