@RequestMapping(method = RequestMethod.PUT, value = "/{region}",
      consumes = {APPLICATION_JSON_UTF8_VALUE}, produces = {
          APPLICATION_JSON_UTF8_VALUE})
  @Operation(summary = "update data for key(s)",
      description = "Update or insert (put) data for keys in a region."
          + " The keys are a comma separated list."
          + " If multiple keys are given then put (create or update) the data for each key."
          + " The op parameter is ignored if more than one key is given."
          + " If op=PUT, the default, create or update data for the given key."
          + " If op=CREATE, create data for the given key if and only if the key does not exit in the region."
          + " If op=REPLACE, update (replace) data for the given key if and only if the key exists in the region."
          + " If op=CAS, update (compare-and-set) value having key with a new value if and only if the \"@old\" value sent matches the current value for the key in the region.")
  @ApiResponses({@ApiResponse(responseCode = "200", description = "OK."),
      @ApiResponse(responseCode = "201", description = "For op=CREATE on success."),
      @ApiResponse(responseCode = "400", description = "Bad Request."),
      @ApiResponse(responseCode = "401", description = "Invalid Username or Password."),
      @ApiResponse(responseCode = "403", description = "Insufficient privileges for operation."),
      @ApiResponse(responseCode = "404",
          description = "Region does not exist or if key is not mapped to some value for REPLACE or CAS."),
      @ApiResponse(responseCode = "409",
          description = "For op=CREATE, key already exist in region. For op=CAS, @old value does not match to the current value in region."),
      @ApiResponse(responseCode = "500", description = "GemFire throws an error or exception.")})
  public ResponseEntity<?> updateKeys(@PathVariable("region") final String encodedRegion,
      @RequestParam(value = "keys") final String[] encodedKeys,
      @RequestParam(value = "op", defaultValue = "PUT") final String opValue,
      @RequestBody final String json) {

    String decodedRegion = decode(encodedRegion);
    String[] decodedKeys = decode(encodedKeys);
    if (!validOp(opValue) && !opValue.equalsIgnoreCase("CREATE")) {
      String errorMessage = String.format(
          "The op parameter (%1$s) is not valid. Valid values are PUT, CREATE, REPLACE, or CAS.",
          opValue);
      return new ResponseEntity<>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST);
    }

    if (decodedKeys.length > 1) {
      // putAll case
      logger.debug("updating keys ({}) for region ({}) op={}", decodedKeys, decodedRegion, opValue);
      securityService.authorize("WRITE", decodedRegion, decodedKeys);
      updateMultipleKeys(decodedRegion, decodedKeys, json);
      HttpHeaders headers = new HttpHeaders();
      headers.setLocation(toUriWithKeys(encodedKeys, encodedRegion));
      return new ResponseEntity<>(headers, HttpStatus.OK);
    } else if (opValue.equalsIgnoreCase("CREATE")) {
      securityService.authorize("DATA", "WRITE", decodedRegion);
      return create(decodedRegion, decodedKeys[0], json, true);
    } else {
      // put case
      logger.debug("updating keys ({}) for region ({}) op={}", decodedKeys, decodedRegion, opValue);
      securityService.authorize("WRITE", decodedRegion, decodedKeys);
      Object existingValue = updateSingleKey(decodedRegion, decodedKeys[0], json, opValue);
      final HttpHeaders headers = new HttpHeaders();
      headers.setLocation(toUriWithKeys(encodedKeys, encodedRegion));
      return new ResponseEntity<>(existingValue, headers,
          (existingValue == null ? HttpStatus.OK : HttpStatus.CONFLICT));
    }
  }
Update data for a key or set of keys

@param encodedRegion gemfire data region
@param encodedKeys comma separated list of keys
@param opValue type of update (put, replace, cas etc)
@param json new data for the key(s)
@return JSON document
geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java