@PUT
  @Path("/{id}")
  @Produces({MediaType.APPLICATION_JSON, "text/uri-list"})
  @ApiOperation(
      value = "Places a new Feature at a particular URI",
      notes =
          "Creates a new Feature entry at the specified URI. If a Feature already exists at this URI,"
              + "it will be replaced. If, instead, no Feature is stored under the specified URI, a new "
              + "Feature entry will be created. Notice that authentication, authorization and accounting (quota) "
              + "restrictions may apply.",
      response = Feature.class,
      position = 4)
  @Consumes(MediaType.APPLICATION_JSON)
  @ApiResponses(
      value = {
        @ApiResponse(code = 200, message = "Feature entry was created successfully."),
        @ApiResponse(
            code = 400,
            message = "Feature entry was not created because the request was malformed"),
        @ApiResponse(
            code = 401,
            message = "You are not authorized to create a feature on the server"),
        @ApiResponse(
            code = 403,
            message = "This request is forbidden (e.g., no authentication token is provided)"),
        @ApiResponse(code = 500, message = "Internal server error - this request cannot be served.")
      })
  public Response putFeature(
      @ApiParam(value = "ID of the Feature.", required = true) @PathParam("id") String id,
      @ApiParam(value = "Feature in JSON", defaultValue = DEFAULT_FEATURE, required = true)
          Feature feature,
      @ApiParam("Clients need to authenticate in order to create resources on the server")
          @HeaderParam("subjectid")
          String subjectId) {
    if (feature == null) {
      ErrorReport report =
          ErrorReportFactory.badRequest(
              "No feature provided; check out the API specs",
              "Clients MUST provide a Feature document in JSON to perform this request");
      return Response.ok(report).status(Response.Status.BAD_REQUEST).build();
    }
    feature.setId(id);

    Feature foundFeature = featureHandler.find(id);
    if (foundFeature != null) {
      featureHandler.edit(feature);
    } else {
      featureHandler.create(feature);
    }

    return Response.ok(feature)
        .status(Response.Status.CREATED)
        .header("Location", uriInfo.getBaseUri().toString() + "feature/" + feature.getId())
        .build();
  }
  @POST
  @Produces({MediaType.APPLICATION_JSON, "text/uri-list"})
  @Consumes(MediaType.APPLICATION_JSON)
  @ApiOperation(
      value = "Creates a new Feature",
      notes =
          "Creates a new feature which is assigned a random unique ID. When creating a new feature, clients must wary not only for "
              + "its syntactic correctness, but also for its semantic completeness. It is strongly recommended to add a comprehensive and "
              + "identifying title to your feature using the <code>meta.titles</code> field, to add a description in <code>meta.descriptions</code> "
              + "and also to add a list of tags in <code>meta.subjects</code> that will facilitate the discoverability of your features later. "
              + "Additionally, all features should be annotated with appropriate ontological classes (from the OpenTox ontology), such as "
              + "<code>ot:Feature</code>, <code>ot:NumericFeature</code> and <code>ot:NominalFeature</code>. Features that are created as "
              + "prediction features for a model or are descriptors that can be calculated using a descriptor calculation web "
              + "service should be linked to this/these service(s) using <code>meta.hasSources</code>. Finally, nominal features should define their "
              + "admissible values in <code>admissibleValues</code>. Malformed feature documents will not be accepted by the server and an "
              + "error report will be generated and returned to the client. Notice also that authentication, authorization and accounting "
              + "restrictions may apply.",
      response = Feature.class)
  @ApiResponses(
      value = {
        @ApiResponse(code = 200, message = "Feature was created successfully."),
        @ApiResponse(code = 400, message = "Bad request: malformed feature"),
        @ApiResponse(code = 401, message = "You are not authorized to access this resource"),
        @ApiResponse(
            code = 403,
            message = "This request is forbidden (e.g., no authentication token is provided)"),
        @ApiResponse(code = 500, message = "Internal server error - this request cannot be served.")
      })
  @Authorize
  public Response createFeature(
      @ApiParam(value = "Clients need to authenticate in order to create resources on the server")
          @HeaderParam("subjectid")
          String subjectId,
      @ApiParam(
              value =
                  "Feature in JSON representation compliant with the Feature specifications. "
                      + "Malformed Feature entries with missing fields will not be accepted.",
              required = true,
              defaultValue = DEFAULT_FEATURE)
          Feature feature)
      throws JaqpotNotAuthorizedException {
    if (feature == null) {
      ErrorReport report =
          ErrorReportFactory.badRequest(
              "No feature provided; check out the API specs",
              "Clients MUST provide a Feature document in JSON to perform this request");
      return Response.ok(report).status(Response.Status.BAD_REQUEST).build();
    }
    if (feature.getMeta() == null) {
      feature.setMeta(new MetaInfo());
    }
    feature.getMeta().setDate(new Date());
    ROG rog = new ROG(true);
    if (feature.getId() == null) {
      feature.setId(rog.nextString(10));
    }
    feature.setCreatedBy(securityContext.getUserPrincipal().getName());

    featureHandler.create(feature);
    return Response.ok(feature)
        .status(Response.Status.OK)
        .header("Location", uriInfo.getBaseUri().toString() + "feature/" + feature.getId())
        .build();
  }