Added BAL/Waitlist Endpoints
diff --git a/README.md b/README.md
index 7fee020..6b07188 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,9 @@
     into a proto file (api_v3.proto). Modify the package to match your project
     (com.partner.mapsbooking.v3.model).
 
+    * If implementing waitlist functionality, repeat the same steps with the
+    [Waitlist Proto Interface](https://developers.google.com/maps-booking/reference/rest-api-v3/waitlists/proto-bundle)
+
 2.  Create a web application project in your IDE named booking_server_v3, add
     Maven support to this project.
 
@@ -70,8 +73,11 @@
 
          protoc --java_out=java resources/api_v3.proto
 
+    * If implementing waitlist functionality, also execute the following:
+         protoc --java_out=java resources/waitlist.proto
+
 5.  Inside of the **src/main/java,** create a new package matching your groupId
-    (com.partner.mapsbooking). Retrieve the sample code from the  repo:
+    (com.partner.mapsbooking). Retrieve the sample code from the repo:
 
          git clone https://maps-booking.googlesource.com/java-maps-booking-rest-server-v3-skeleton
 
@@ -124,6 +130,8 @@
                       |---RestAuthenticationFilter.java
                   |---v3.model
                       |---ApiV3.java
+                      |---Waitlist.java
           |---resources
               |---api_v3.proto
+              |---waitlist.proto
       |---test
diff --git a/authentication/AuthenticationService.java b/authentication/AuthenticationService.java
index 745a882..d8859e3 100644
--- a/authentication/AuthenticationService.java
+++ b/authentication/AuthenticationService.java
@@ -32,8 +32,8 @@
 package com.partner.mapsbooking.authentication;
 
 import java.io.IOException;
+import java.util.Base64;
 import java.util.StringTokenizer;
-import sun.misc.BASE64Decoder;
 
 /** Check the credentials by validates the data included in authorization headers. */
 public class AuthenticationService {
@@ -50,7 +50,7 @@
     final String encodedUserPassword = credential.replaceFirst("Basic" + " ", "");
     String usernameAndPassword = null;
     try {
-      byte[] decodedBytes = new BASE64Decoder().decodeBuffer(encodedUserPassword);
+      byte[] decodedBytes = Base64.getDecoder().decode(encodedUserPassword);
       usernameAndPassword = new String(decodedBytes, "UTF-8");
     } catch (IOException e) {
       e.printStackTrace();
diff --git a/rest/BookingService.java b/rest/BookingService.java
index 9c46024..9711f7b 100644
--- a/rest/BookingService.java
+++ b/rest/BookingService.java
@@ -33,7 +33,8 @@
 
 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf.util.JsonFormat;
-import com.partner.mapsbooking.v3.model.ApiV3;
+import ext.maps.booking.partner.v3.ApiV3;
+import ext.maps.booking.partner.v3.Waitlist;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
@@ -49,11 +50,11 @@
     return JsonFormat.printer().preservingProtoFieldNames();
   }
 
+  @Path("/HealthCheck")
   @GET
   @Produces(MediaType.TEXT_PLAIN)
   public String checkServer() {
-    // method for testing
-    return "Got it!";
+    return "200";
   }
 
   @Path("/CheckAvailability")
@@ -98,6 +99,60 @@
     throw new UnsupportedOperationException("Not implemented yet");
   }
 
+  @Path("/BatchAvailabilityLookup")
+  @POST
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  public String batchAvailabilityLookup(String request) throws InvalidProtocolBufferException {
+
+    // use JsonFormat.Parser to convert Json String into protocol buffer
+    ApiV3.BatchAvailabilityLookupRequest.Builder requestBuilder
+        = ApiV3.BatchAvailabilityLookupRequest.newBuilder();
+    JsonFormat.Parser jsonParser = JsonFormat.parser();
+    jsonParser.merge(request, requestBuilder);
+    ApiV3.BatchAvailabilityLookupRequest batchAvailabilityLookupRequest = requestBuilder.build();
+
+    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
+    // return corresponding response and HTTP code
+    // Normal path: get response object from the helper function
+    ApiV3.BatchAvailabilityLookupResponse response
+        = performBatchAvailabilityLookup(batchAvailabilityLookupRequest);
+
+    // use JsonFormat to convert protocol buffer to Json
+    String jsonResponse = jsonPrinter().print(response);
+    return jsonResponse;
+  }
+
+  // TODO(partner): Implement this method to perform batch availability lookup
+  private ApiV3.BatchAvailabilityLookupResponse performBatchAvailabilityLookup(
+      ApiV3.BatchAvailabilityLookupRequest request) {
+    //        BatchAvailabilityLookup logic:
+    //        e.g.
+    //        String merchantId = request.getMerchantId();
+    //        List<ApiV3.SlotTime> requestedSlotTimes = request.getSlotTimeList();
+    //
+    //        List<ApiV3.SlotTimeAvailability> slotTimeAvailabilities =
+    //             new ArrayList<SlotTimeAvailability>();
+    //
+    //        loop through all requested slotTimes &
+    //          populate slotTimeAvailabilities with availability status:
+    //        e.g
+    //        for (ApiV3.SlotTime slotTime : requestedSlotTimes) {
+    //            slotTimeAvailabilities.add(SlotTimeAvailability.newBuilder()
+    //                .setSlotTime(slotTime)
+    //                .setAvailable(true)
+    //                .build());
+    //        }
+    //
+    //        ApiV3.BatchAvailabilityLookupResponse response =
+    //            ApiV3.BatchAvailabilityLookupResponse.newBuilder()
+    //                .addAllSlotTimeAvailability(slotTimeAvailabilities).build();
+    //
+    //        return response;
+
+    throw new UnsupportedOperationException("Not implemented yet");
+  }
+
   @Path("/CreateBooking")
   @POST
   @Produces(MediaType.APPLICATION_JSON)
@@ -377,7 +432,7 @@
     //        Create order business logic:
     //        e.g.
     //        ApiV3.Order order = request.getOrder();
-
+    //
     //        normal case -> create this order in the backend, return response:
     //        ApiV3.CreateOrderResponse response = ApiV3.CreateOrderResponse.newBuilder()
     //                .setOrder(order)
@@ -446,4 +501,177 @@
 
     throw new UnsupportedOperationException("Not implemented yet");
   }
+
+
+  /**
+   * Waitlist Implementation
+   * Proto File -
+   * https://developers.google.com/maps-booking/reference/rest-api-v3/waitlists/proto-bundle
+   */
+  @Path("/BatchGetWaitEstimates")
+  @POST
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  public String batchGetWaitEstimates(String request) throws InvalidProtocolBufferException {
+
+    // use JsonFormat.Parser to convert Json String into protocol buffer
+    Waitlist.BatchGetWaitEstimatesRequest.Builder requestBuilder
+        = Waitlist.BatchGetWaitEstimatesRequest.newBuilder();
+    JsonFormat.Parser jsonParser = JsonFormat.parser();
+    jsonParser.merge(request, requestBuilder);
+    Waitlist.BatchGetWaitEstimatesRequest batchGetWaitEstimatesRequest = requestBuilder.build();
+
+    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
+    // return corresponding response and HTTP code
+    //
+    // Normal path: get response object from the helper function
+    Waitlist.BatchGetWaitEstimatesResponse response
+        = performBatchGetWaitEstimates(batchGetWaitEstimatesRequest);
+
+    // use JsonFormat to convert protocol buffer to Json
+    String jsonResponse = jsonPrinter().print(response);
+    return jsonResponse;
+  }
+
+  // TODO(partner): Implement this method to return wait estimates based on party size
+  private Waitlist.BatchGetWaitEstimatesResponse performBatchGetWaitEstimates(
+      Waitlist.BatchGetWaitEstimatesRequest request) {
+    // String merchantId = request.getMerchantId();
+    // String serviceId = request.getServiceId();
+    //
+    // List<Integer> requestedPartySizes = request.getPartySizeList();
+    //
+    // Waitlist.BatchGetWaitEstimatesResponse response
+    //     = Waitlist.BatchGetWaitEstimatesResponse.newBuilder().setWaitlistStatus(
+    //           WaitlistStatus.OPEN).addAllWaitEstimate(...).build();
+    //
+    // return response;
+
+    throw new UnsupportedOperationException("Not implemented yet");
+  }
+
+  @Path("/CreateWaitlistEntry")
+  @POST
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  public String createWaitlistEntry(String request) throws InvalidProtocolBufferException {
+
+    // use JsonFormat.Parser to convert Json String into protocol buffer
+    Waitlist.CreateWaitlistEntryRequest.Builder requestBuilder
+        = Waitlist.CreateWaitlistEntryRequest.newBuilder();
+    JsonFormat.Parser jsonParser = JsonFormat.parser();
+    jsonParser.merge(request, requestBuilder);
+    Waitlist.CreateWaitlistEntryRequest createWaitlistEntryRequest = requestBuilder.build();
+
+    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
+    // return corresponding response and HTTP code
+    //
+    // Normal path: get response object from the helper function
+    Waitlist.CreateWaitlistEntryResponse response
+        = performCreateWaitlistEntry(createWaitlistEntryRequest);
+
+    // use JsonFormat to convert protocol buffer to Json
+    String jsonResponse = jsonPrinter().print(response);
+    return jsonResponse;
+  }
+
+  // TODO(partner): Implement this method to create wait list entry based on request
+  private Waitlist.CreateWaitlistEntryResponse performCreateWaitlistEntry(
+      Waitlist.CreateWaitlistEntryRequest request) {
+    // String merchantId = request.getMerchantId();
+    // String serviceId = request.getServiceId();
+    // int partySize = request.getPartySize();
+    //
+    // Waitlist.UserInformation userInformation = request.getUserInformation();
+    // String idempotencyToken = request.getIdempotencyToken();
+    //
+    // Normal Case -> return a unique waitlist_entry_id e.g
+    // Waitlist.CreateWaitlistEntryResponse response
+    //     = Waitlist.CreateWaitlistEntryResponse.newBuilder().setWaitlistEntryId(...).build();
+    //
+    // Business logic error -> set the WaitlistBusinessLogicFailure in the response
+    //
+    // Waitlist.WaitlistBusinessLogicFailure waitlistBusinessLogicFailure
+    //     = Waitlist.WaitlistBusinessLogicFailure.newBuilder()
+    //         .setCause(Cause.WAITLIST_FULL).setDescription("").build();
+    //
+    // Waitlist.CreateWaitlistEntryResponse response
+    //     = Waitlist.CreateWaitlistEntryResponse.newBuilder()
+    //         .setWaitlistBusinessLogicFailure(waitlistBusinessLogicFailure).build();
+    //
+    // return response;
+
+    throw new UnsupportedOperationException("Not implemented yet");
+  }
+
+  @Path("/GetWaitlistEntry")
+  @POST
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  public String getWaitlistEntry(String request) throws InvalidProtocolBufferException {
+
+    // use JsonFormat.Parser to convert Json String into protocol buffer
+    Waitlist.GetWaitlistEntryRequest.Builder requestBuilder
+        = Waitlist.GetWaitlistEntryRequest.newBuilder();
+    JsonFormat.Parser jsonParser = JsonFormat.parser();
+    jsonParser.merge(request, requestBuilder);
+    Waitlist.GetWaitlistEntryRequest getWaitlistEntryRequest = requestBuilder.build();
+
+    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
+    // return corresponding response and HTTP code
+    //
+    // Normal path: get response object from the helper function
+    Waitlist.GetWaitlistEntryResponse response
+        = performGetWaitlistEntry(getWaitlistEntryRequest);
+
+    // use JsonFormat to convert protocol buffer to Json
+    String jsonResponse = jsonPrinter().print(response);
+    return jsonResponse;
+  }
+
+  // TODO(partner): Implement this method to return waitlist entry
+  private Waitlist.GetWaitlistEntryResponse performGetWaitlistEntry(
+      Waitlist.GetWaitlistEntryRequest request) {
+    // String waitlistEntryId = request.getWaitlistEntryId();
+    //
+    // Waitlist.GetWaitlistEntryResponse response = Waitlist.GetWaitlistEntryResponse.newBuilder()
+    //     .setWaitlistEntry(WaitlistEntry...).build();
+    //
+    // return response;
+
+    throw new UnsupportedOperationException("Not implemented yet");
+  }
+
+  @Path("/DeleteWaitlistEntry")
+  @POST
+  @Produces(MediaType.APPLICATION_JSON)
+  @Consumes(MediaType.APPLICATION_JSON)
+  public String deleteWaitlistEntry(String request) throws InvalidProtocolBufferException {
+
+    // use JsonFormat.Parser to convert Json String into protocol buffer
+    Waitlist.DeleteWaitlistEntryRequest.Builder requestBuilder
+        = Waitlist.DeleteWaitlistEntryRequest.newBuilder();
+    JsonFormat.Parser jsonParser = JsonFormat.parser();
+    jsonParser.merge(request, requestBuilder);
+    Waitlist.DeleteWaitlistEntryRequest deleteWaitlistEntryRequest = requestBuilder.build();
+
+    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
+    // return corresponding response and HTTP code
+    //
+    // If entry exists, delete it. Otherwise throw 404
+    performDeleteWaitlistEntry(deleteWaitlistEntryRequest);
+
+    return "";
+  }
+
+  // TODO(partner): Implement this method to return waitlist entry
+  private void performDeleteWaitlistEntry(Waitlist.DeleteWaitlistEntryRequest request) {
+
+    // String waitlistEntryId = request.getWaitlistEntryId();
+    // If waitlist entry Id exists, delete it
+    // If waitlist entry id doesn't exist, return 404
+    // throw new WebApplicationException(404);
+
+    throw new UnsupportedOperationException("Not implemented yet");
+  }
 }