@Test(
      dataProvider =
          com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX
              + "clientDataDataProvider")
  public void testUpdate(RestClient restClient, RootBuilderWrapper<Long, Greeting> builders)
      throws RemoteInvocationException, CloneNotSupportedException {
    // GET
    Request<Greeting> request = builders.get().id(1L).build();
    Response<Greeting> greetingResponse1 = restClient.sendRequest(request).getResponse();

    String response1 = greetingResponse1.getEntity().getMessage();
    Assert.assertNotNull(response1);

    // POST
    Greeting greeting = new Greeting(greetingResponse1.getEntity().data().copy());
    greeting.setMessage(response1 + "Again");

    Request<EmptyRecord> writeRequest = builders.update().id(1L).input(greeting).build();
    Response<EmptyRecord> updateResponse = restClient.sendRequest(writeRequest).getResponse();
    Assert.assertNull(updateResponse.getHeader(RestConstants.HEADER_CONTENT_TYPE));

    // GET again, to verify that our POST worked.
    Request<Greeting> request2 = builders.get().id(1L).build();
    Response<Greeting> greetingResponse2 = restClient.sendRequest(request2).getResponse();

    String response2 = greetingResponse2.getEntity().getMessage();
    Assert.assertEquals(response2, response1 + "Again");
  }
  /**
   * a more concrete example of custom action<br>
   * resource level determines the granularity of the action<br>
   * mismatching the resource level in the request throws exception and will respond HTTP 400
   *
   * @param resource Instance of the resource class. This is not part of the action method and is
   *     needed because this implementation is not an actual resource.
   */
  @Action(name = "updateTone", resourceLevel = ResourceLevel.ENTITY)
  // The base resource parameter gets special handling in the generator. It is set to the actual
  // resource class instance, and is not part of the generated REST method.
  public Greeting updateTone(
      BaseResource resource,
      @ActionParam("newTone") @Optional Tone newTone,
      @ActionParam("delOld") @Optional("false") Boolean delOld) {
    // the way to get entity key in action
    Long key = resource.getContext().getPathKeys().get(_resourceName + "Id");
    Greeting g = _db.get(key);
    if (g == null) {
      // HTTP 404
      return g;
    }

    // delete existing Greeting and assign new key
    if (delOld) {
      _db.remove(key);
      key = _idSeq.incrementAndGet();
      g.setId(key);
    }

    Tone t;
    // newTone is an optional parameter
    // omitting it in request results a null value
    if (newTone == null) {
      t = DEFAULT_TONE;
    } else {
      t = newTone;
    }
    g.setTone(t);
    _db.put(key, g);

    return g;
  }
 private static List<Greeting> generateCreate(int num) {
   List<Greeting> creates = new ArrayList<Greeting>();
   for (int i = 0; i < num; ++i) {
     Greeting greeting = new Greeting();
     greeting.setMessage("create message").setTone(Tone.FRIENDLY);
     creates.add(greeting);
   }
   return creates;
 }
 private static Map<Long, Greeting> generateUpdates(Long[] ids) {
   Map<Long, Greeting> updates = new HashMap<Long, Greeting>();
   for (long l : ids) {
     Greeting greeting = new Greeting();
     greeting.setId(l).setMessage("update message").setTone(Tone.SINCERE);
     updates.put(l, greeting);
   }
   return updates;
 }
 // These CRUD annotations are MANDATORY for the code generator because we want to generate
 // implementations which do not use the templates, e.g. Task
 @RestMethod.Create
 public CreateResponse create(
     Greeting entity, @QueryParam("isNullId") @Optional("false") boolean isNullId) {
   entity.setId(_idSeq.incrementAndGet());
   _db.put(entity.getId(), entity);
   if (isNullId) {
     return new CreateResponse(null, HttpStatus.S_201_CREATED);
   }
   return new CreateResponse(entity.getId());
 }
 public GreetingsResourceImpl(String resourceName) {
   for (int i = 0; i < INITIAL_SIZE; i++) {
     Greeting g =
         new Greeting()
             .setId(_idSeq.incrementAndGet())
             .setMessage(INITIAL_MESSAGES[i])
             .setTone(INITIAL_TONES[i]);
     _db.put(g.getId(), g);
   }
   _resourceName = resourceName;
 }
  // TODO modify this method to accept a CollectionRequest as it's first parameter once our server
  // code has been
  //      updated to work with the new representation of BatchUpdateRequests and
  // BatchPartialUpdateRequests. As of now
  //      we are still converting to the old representation using
  // CollectionRequestUtil.convertToBatchRequest
  private static void checkInput(
      DataMap dataMap, Map<Long, Greeting> inputMap, Set<String> uriIds) {
    Assert.assertEquals(dataMap.size(), uriIds.size());

    for (String key : dataMap.keySet()) {
      DataMap inputDM = dataMap.getDataMap(key);
      Greeting expectedGreeting = inputMap.get(Long.parseLong(key));
      Assert.assertTrue(uriIds.contains(key));
      Assert.assertTrue(inputDM.equals(expectedGreeting.data()));
    }
  }
 @Test(
     dataProvider =
         com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX
             + "clientDataDataProvider")
 public void testGet(RestClient restClient, RootBuilderWrapper<Long, Greeting> builders)
     throws RemoteInvocationException {
   Request<Greeting> request = builders.get().id(1L).build();
   Response<Greeting> response = restClient.sendRequest(request).getResponse();
   Greeting greeting = response.getEntity();
   Assert.assertEquals(greeting.getId(), new Long(1));
 }
 @RestMethod.GetAll
 public List<Greeting> getAll(@PagingContextParam PagingContext ctx) {
   // Deterministic behaviour of getAll to make it easier to test as part of the integration test
   // suite
   // Just return those greetings that have "GetAll" present in their message
   List<Greeting> greetings = new ArrayList<Greeting>();
   for (Greeting greeting : _db.values()) {
     if (greeting.getMessage().contains("GetAll")) {
       greetings.add(greeting);
     }
   }
   return greetings;
 }
  @Test(
      dataProvider =
          com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX
              + "buildersClientDataDataProvider")
  public void testCreateId(RestClient restClient, RestliRequestOptions requestOptions)
      throws RemoteInvocationException {
    Greeting greeting = new Greeting();
    greeting.setMessage("Hello there!");
    greeting.setTone(Tone.FRIENDLY);

    final GreetingsRequestBuilders builders = new GreetingsRequestBuilders(requestOptions);

    CreateIdRequest<Long, Greeting> createRequest = builders.create().input(greeting).build();
    Response<IdResponse<Long>> response = restClient.sendRequest(createRequest).getResponse();
    Assert.assertNull(response.getHeader(RestConstants.HEADER_CONTENT_TYPE));
    @SuppressWarnings("unchecked")
    long id = response.getEntity().getId();
    @SuppressWarnings("deprecation")
    String stringId = response.getId();
    Assert.assertEquals(id, Long.parseLong(stringId));

    Request<Greeting> getRequest = builders.get().id(id).build();
    Response<Greeting> getResponse = restClient.sendRequest(getRequest).getResponse();
    Greeting responseGreeting = getResponse.getEntity();

    Assert.assertEquals(responseGreeting.getMessage(), greeting.getMessage());
    Assert.assertEquals(responseGreeting.getTone(), greeting.getTone());
  }
  @Test(
      dataProvider =
          com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX
              + "clientDataDataProvider")
  public void testFinder(RestClient restClient, RootBuilderWrapper<Long, Greeting> builders)
      throws RemoteInvocationException {
    Request<CollectionResponse<Greeting>> request =
        builders.findBy("Search").setQueryParam("tone", Tone.SINCERE).paginate(1, 2).build();

    Response<CollectionResponse<Greeting>> response = restClient.sendRequest(request).getResponse();

    CollectionResponse<Greeting> collectionResponse = response.getEntity();
    List<Greeting> greetings = collectionResponse.getElements();

    for (Greeting g : greetings) {
      Assert.assertEquals(g.getTone(), Tone.SINCERE);
    }
    collectionResponse.getPaging().getLinks();
  }
  @Finder("search")
  public List<Greeting> search(
      @PagingContextParam PagingContext ctx, @QueryParam("tone") @Optional Tone tone) {
    List<Greeting> greetings = new ArrayList<Greeting>();
    int idx = 0;
    int start = ctx.getStart();
    int stop = start + ctx.getCount();
    for (Greeting g : _db.values()) {
      if (idx++ >= ctx.getStart()) {
        if (tone == null || g.getTone().equals(tone)) {
          greetings.add(g);
        }

        if (idx == stop) {
          break;
        }
      }
    }
    return greetings;
  }
  @Finder("searchWithTones")
  public List<Greeting> searchWithTones(
      @PagingContextParam PagingContext ctx, @QueryParam("tones") @Optional Tone[] tones) {
    Set<Tone> toneSet = new HashSet<Tone>(Arrays.asList(tones));
    List<Greeting> greetings = new ArrayList<Greeting>();
    int idx = 0;
    int start = ctx.getStart();
    int stop = start + ctx.getCount();
    for (Greeting g : _db.values()) {
      if (idx++ >= ctx.getStart()) {
        if (tones == null || toneSet.contains(g.getTone())) {
          greetings.add(g);
        }

        if (idx == stop) {
          break;
        }
      }
    }
    return greetings;
  }
  @Test(
      dataProvider =
          com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX
              + "clientDataDataProvider")
  public void testAction(RestClient restClient, RootBuilderWrapper<Long, Greeting> builders)
      throws RemoteInvocationException {
    Request<Greeting> request =
        builders
            .<Greeting>action("SomeAction")
            .id(1L)
            .setActionParam("A", 1)
            .setActionParam("B", "")
            .setActionParam("C", new TransferOwnershipRequest())
            .setActionParam("D", new TransferOwnershipRequest())
            .setActionParam("E", 3)
            .build();

    Response<Greeting> response = restClient.sendRequest(request).getResponse();

    Greeting greeting = response.getEntity();
    Assert.assertEquals(greeting.getMessage(), "This is a newly created greeting");
  }
  @Test(
      dataProvider =
          com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX
              + "requestBuilderDataProvider")
  public void testPostsWithCharset(RootBuilderWrapper<Long, Greeting> builders)
      throws RemoteInvocationException {
    RestClient restClient = new RestClient(CLIENT, URI_PREFIX);

    Request<Greeting> request =
        builders
            .<Greeting>action("SomeAction")
            .id(1L)
            .setActionParam("A", 1)
            .setActionParam("B", "")
            .setActionParam("C", new TransferOwnershipRequest())
            .setActionParam("D", new TransferOwnershipRequest())
            .setActionParam("E", 3)
            .setHeader("Content-Type", "application/json; charset=UTF-8")
            .build();

    Response<Greeting> response = restClient.sendRequest(request).getResponse();

    Greeting actionGreeting = response.getEntity();
    Assert.assertEquals(actionGreeting.getMessage(), "This is a newly created greeting");

    Greeting createGreeting = new Greeting();
    createGreeting.setMessage("Hello there!");
    createGreeting.setTone(Tone.FRIENDLY);

    Request<EmptyRecord> createRequest =
        builders
            .create()
            .input(createGreeting)
            .setHeader("Content-Type", "application/json; charset=UTF-8")
            .build();
    Response<EmptyRecord> emptyRecordResponse = restClient.sendRequest(createRequest).getResponse();
    Assert.assertNull(emptyRecordResponse.getHeader(RestConstants.HEADER_CONTENT_TYPE));
  }
  private static Collection<ScatterGatherBuilder.RequestInfo<Greeting>>
      buildScatterGatherGetRequests(ScatterGatherBuilder<Greeting> sg, Long[] ids)
          throws ServiceUnavailableException {
    Request<BatchResponse<Greeting>> request =
        new GreetingsBuilders()
            .batchGet()
            .ids(ids)
            .fields(Greeting.fields().message())
            .setParam("foo", "bar")
            .build();

    return sg.buildRequestsV2((BatchGetRequest<Greeting>) request, new RequestContext())
        .getRequestInfo();
  }
  @Finder("searchWithFacets")
  public CollectionResult<Greeting, SearchMetadata> searchWithFacets(
      @PagingContextParam PagingContext ctx, @QueryParam("tone") @Optional Tone tone) {
    List<Greeting> greetings = search(ctx, tone);

    Map<Tone, Integer> toneCounts = new HashMap<Tone, Integer>();
    for (Greeting g : greetings) {
      if (!toneCounts.containsKey(g.getTone())) {
        toneCounts.put(g.getTone(), 0);
      }
      toneCounts.put(g.getTone(), toneCounts.get(g.getTone()) + 1);
    }

    SearchMetadata metadata = new SearchMetadata();
    metadata.setFacets(new ToneFacetArray());
    for (Map.Entry<Tone, Integer> entry : toneCounts.entrySet()) {
      ToneFacet f = new ToneFacet();
      f.setTone(entry.getKey());
      f.setCount(entry.getValue());
      metadata.getFacets().add(f);
    }

    return new CollectionResult<Greeting, SearchMetadata>(greetings, null, metadata);
  }