/**
   * Submits the entity definitions (instances). The body contains the JSONArray of entity json. The
   * service takes care of de-duping the entities based on any unique attribute for the give type.
   */
  @POST
  @Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
  @Produces(Servlets.JSON_MEDIA_TYPE)
  public Response submit(@Context HttpServletRequest request) {

    String entityJson = null;
    try {
      String entities = Servlets.getRequestPayload(request);

      // Handle backward compatibility - if entities is not JSONArray, convert to JSONArray
      try {
        new JSONArray(entities);
      } catch (JSONException e) {
        final String finalEntities = entities;
        entities =
            new JSONArray() {
              {
                put(finalEntities);
              }
            }.toString();
      }

      entityJson = AtlasClient.toString(new JSONArray(entities));
      LOG.info("submitting entities {} ", entityJson);

      final List<String> guids = metadataService.createEntities(entities);
      LOG.info("Created entities {}", guids);
      JSONObject response = getResponse(new AtlasClient.EntityResult(guids, null, null));

      URI locationURI = getLocationURI(guids);

      return Response.created(locationURI).entity(response).build();

    } catch (EntityExistsException e) {
      LOG.error("Unique constraint violation for entity entityDef={}", entityJson, e);
      throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.CONFLICT));
    } catch (ValueConversionException ve) {
      LOG.error(
          "Unable to persist entity instance due to a deserialization error entityDef={}",
          entityJson,
          ve);
      throw new WebApplicationException(
          Servlets.getErrorResponse(ve.getCause(), Response.Status.BAD_REQUEST));
    } catch (AtlasException | IllegalArgumentException e) {
      LOG.error("Unable to persist entity instance entityDef={}", entityJson, e);
      throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
    } catch (Throwable e) {
      LOG.error("Unable to persist entity instance entityDef={}", entityJson, e);
      throw new WebApplicationException(
          Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
    }
  }
  /**
   * Complete update of a set of entities - the values not specified will be replaced with
   * null/removed Adds/Updates given entities identified by its GUID or unique attribute
   *
   * @return response payload as json
   */
  @PUT
  @Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
  @Produces(Servlets.JSON_MEDIA_TYPE)
  public Response updateEntities(@Context HttpServletRequest request) {

    String entityJson = null;
    try {
      final String entities = Servlets.getRequestPayload(request);

      entityJson = AtlasClient.toString(new JSONArray(entities));
      LOG.info("updating entities {} ", entityJson);

      AtlasClient.EntityResult entityResult = metadataService.updateEntities(entities);
      LOG.info("Updated entities: {}", entityResult);

      JSONObject response = getResponse(entityResult);
      return Response.ok(response).build();
    } catch (EntityExistsException e) {
      LOG.error("Unique constraint violation for entityDef={}", entityJson, e);
      throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.CONFLICT));
    } catch (ValueConversionException ve) {
      LOG.error(
          "Unable to persist entity instance due to a deserialization error entityDef={}",
          entityJson,
          ve);
      throw new WebApplicationException(
          Servlets.getErrorResponse(ve.getCause(), Response.Status.BAD_REQUEST));
    } catch (AtlasException | IllegalArgumentException e) {
      LOG.error("Unable to persist entity instance entityDef={}", entityJson, e);
      throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
    } catch (Throwable e) {
      LOG.error("Unable to persist entity instance entityDef={}", entityJson, e);
      throw new WebApplicationException(
          Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
    }
  }
  /**
   * Adds/Updates given entity identified by its unique attribute( entityType, attributeName and
   * value) Updates support only partial update of an entity - Adds/updates any new values specified
   * Updates do not support removal of attribute values
   *
   * @param entityType the entity type
   * @param attribute the unique attribute used to identify the entity
   * @param value the unique attributes value
   * @param request The updated entity json
   * @return response payload as json The body contains the JSONArray of entity json. The service
   *     takes care of de-duping the entities based on any unique attribute for the give type.
   */
  @POST
  @Path("qualifiedName")
  @Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
  @Produces(Servlets.JSON_MEDIA_TYPE)
  public Response updateByUniqueAttribute(
      @QueryParam("type") String entityType,
      @QueryParam("property") String attribute,
      @QueryParam("value") String value,
      @Context HttpServletRequest request) {

    String entityJson = null;
    try {
      entityJson = Servlets.getRequestPayload(request);

      LOG.info(
          "Partially updating entity by unique attribute {} {} {} {} ",
          entityType,
          attribute,
          value,
          entityJson);

      Referenceable updatedEntity = InstanceSerialization.fromJsonReferenceable(entityJson, true);

      AtlasClient.EntityResult entityResult =
          metadataService.updateEntityByUniqueAttribute(
              entityType, attribute, value, updatedEntity);
      LOG.info("Updated entities: {}", entityResult);

      JSONObject response = getResponse(entityResult);
      return Response.ok(response).build();
    } catch (ValueConversionException ve) {
      LOG.error(
          "Unable to persist entity instance due to a deserialization error {} ", entityJson, ve);
      throw new WebApplicationException(
          Servlets.getErrorResponse(ve.getCause(), Response.Status.BAD_REQUEST));
    } catch (EntityExistsException e) {
      LOG.error("Unique constraint violation for entity {} ", entityJson, e);
      throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.CONFLICT));
    } catch (EntityNotFoundException e) {
      LOG.error(
          "An entity with type={} and qualifiedName={} does not exist {} ",
          entityType,
          value,
          entityJson,
          e);
      throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.NOT_FOUND));
    } catch (AtlasException | IllegalArgumentException e) {
      LOG.error(
          "Unable to partially update entity {} {} " + entityType + ":" + attribute + "." + value,
          entityJson,
          e);
      throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
    } catch (Throwable e) {
      LOG.error(
          "Unable to partially update entity {} {} " + entityType + ":" + attribute + "." + value,
          entityJson,
          e);
      throw new WebApplicationException(
          Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
    }
  }