Initial commit of sample java rest server
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6f3d5f2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,125 @@
+# Booking Server (REST) Skeleton for Java
+
+This ia a reference implementation for API v3 Booking server based on:
+
+* [google-protobuf](https://developers.google.com/protocol-buffers/docs/overview)
+* [Jersey RESTful Web Services](https://jersey.github.io/)
+
+### Prerequisites
+
+Require installations of
+
+* [Apache Maven](https://maven.apache.org/)
+* [Protocol compiler for java](https://github.com/google/protobuf)
+* [Apache Tomcat](http://tomcat.apache.org/)
+
+### Get Started
+
+1. Copy the [Proto
+ Interface](https://developers.google.com/maps-booking/reference/rest-api-v3/proto-bundle)
+ into a proto file (api_v3.proto). Modify the package to match your project
+ (com.partner.mapsbooking.v3.model).
+
+2. Create a web application project in your IDE named booking_server_v3, add
+ Maven support to this project.
+
+3. Place your proto file under the **src/main/resources,** add dependencies for
+ Jersey and protocol buffers runtime to the Maven **pom.xml** file:
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey</groupId>
+ <artifactId>jersey-bom</artifactId>
+ <version>${jersey.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <version>2.27</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>3.5.1</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-protobuf</artifactId>
+ <version>1.11.0</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <java.version>1.8</java.version>
+ <jersey.version>2.23.2</jersey.version>
+ </properties>
+
+4. Execute the following command under **src/main** to auto-generate a source
+ file for the classes defined in the proto file:
+
+ protoc --java_out=java resources/api_v3.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, place the
+ files under your package, follow the **TODOs** to complete your
+ implementation.
+
+6. Configure your servlet by modifying the **web.xml** file:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
+ version="4.0">
+
+ <servlet>
+ <servlet-name>Booking Rest Server</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>com.partner.mapsbooking</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Booking Rest Server</servlet-name>
+ <url-pattern>/mapsbooking/*</url-pattern>
+ </servlet-mapping>
+ </web-app>
+
+7. In the Run Configurations, set up a Tomcat server configuration. Add all the
+ jars to the /WEB_INF/lib directory (project structure -> artifacts -> After
+ selecting all jars right click and choose "Put into /WEB-INF/lib").
+
+8. Run Tomcat to start your server.
+
+### Final Directory Structure
+
+ src
+ |---main
+ |---java
+ |---com.partner.mapsbooking
+ |---rest
+ |---BookingService.java
+ |---BookingExceptionMapper.java
+ |---Error.java
+ |---authentication
+ |---AuthenticationService.java
+ |---RestAuthenticationFilter.java
+ |---v3.model
+ |---ApiV3.java
+ |---resources
+ |---api_v3.proto
+ |---test
diff --git a/authentication/AuthenticationService.java b/authentication/AuthenticationService.java
new file mode 100644
index 0000000..745a882
--- /dev/null
+++ b/authentication/AuthenticationService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.partner.mapsbooking.authentication;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+import sun.misc.BASE64Decoder;
+
+/** Check the credentials by validates the data included in authorization headers. */
+public class AuthenticationService {
+ // TODO(partner): set your user name and password
+ private static String USERNAME = "admin";
+ private static String PASSWORD = "password";
+
+ public boolean authenticate(String credential) {
+ if (null == credential) {
+ return false;
+ }
+ // header value format will be "Basic encoded string" for Basic
+ // authentication. Example "Basic YWRtaW46YWRtaW4="
+ final String encodedUserPassword = credential.replaceFirst("Basic" + " ", "");
+ String usernameAndPassword = null;
+ try {
+ byte[] decodedBytes = new BASE64Decoder().decodeBuffer(encodedUserPassword);
+ usernameAndPassword = new String(decodedBytes, "UTF-8");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");
+ final String username = tokenizer.nextToken();
+ final String password = tokenizer.nextToken();
+
+ boolean authenticationStatus = USERNAME.equals(username) && PASSWORD.equals(password);
+ return authenticationStatus;
+ }
+}
diff --git a/authentication/RestAuthenticationFilter.java b/authentication/RestAuthenticationFilter.java
new file mode 100644
index 0000000..0ecfc20
--- /dev/null
+++ b/authentication/RestAuthenticationFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.partner.mapsbooking.authentication;
+
+import javax.ws.rs.NotAuthorizedException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.ext.Provider;
+
+/** Do the authentication by inspecting the authorization headers. */
+@Provider
+public class RestAuthenticationFilter implements ContainerRequestFilter {
+
+ public void filter(ContainerRequestContext containerRequest) throws WebApplicationException {
+
+ String authCredentials = containerRequest.getHeaderString(HttpHeaders.AUTHORIZATION);
+
+ AuthenticationService authenticationService = new AuthenticationService();
+
+ boolean authStatus = authenticationService.authenticate(authCredentials);
+
+ if (!authStatus) {
+ throw new NotAuthorizedException("Wrong username/password!");
+ }
+ }
+}
diff --git a/rest/BookingExceptionMapper.java b/rest/BookingExceptionMapper.java
new file mode 100644
index 0000000..be6e361
--- /dev/null
+++ b/rest/BookingExceptionMapper.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.partner.mapsbooking.rest;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import javax.ws.rs.NotAuthorizedException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/** Map exceptions to responses by implementing the ExceptionMapper interface,
+ * which handles unexpected errors.
+ */
+@Provider
+public class BookingExceptionMapper implements ExceptionMapper<Throwable> {
+
+ public Response toResponse(Throwable ex) {
+ javax.ws.rs.core.Response.StatusType type = getStatusType(ex);
+ Error error = new Error(type.getStatusCode(), type.getReasonPhrase(), ex.getMessage());
+
+ return javax.ws.rs.core.Response.status(type.getStatusCode())
+ .entity(error)
+ .type(MediaType.APPLICATION_JSON)
+ .build();
+ }
+
+ private javax.ws.rs.core.Response.StatusType getStatusType(Throwable ex) {
+ if (ex instanceof InvalidProtocolBufferException) {
+ return javax.ws.rs.core.Response.Status.BAD_REQUEST;
+ } else if (ex instanceof NotAuthorizedException) {
+ return javax.ws.rs.core.Response.Status.UNAUTHORIZED;
+ } else if (ex instanceof NotFoundException) {
+ return javax.ws.rs.core.Response.Status.NOT_FOUND;
+ } else if (ex instanceof UnsupportedOperationException) {
+ return javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED;
+ }
+ // TODO(partner): implement handlers for other exception you throw
+ return javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+ }
+}
diff --git a/rest/BookingService.java b/rest/BookingService.java
new file mode 100644
index 0000000..9c46024
--- /dev/null
+++ b/rest/BookingService.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright 2018, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.partner.mapsbooking.rest;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.util.JsonFormat;
+import com.partner.mapsbooking.v3.model.ApiV3;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/** Booking REST Server for API v3 with authentication. */
+@Path("/v3")
+public class BookingService {
+
+ private JsonFormat.Printer jsonPrinter() {
+ return JsonFormat.printer().preservingProtoFieldNames();
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String checkServer() {
+ // method for testing
+ return "Got it!";
+ }
+
+ @Path("/CheckAvailability")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String checkAvailability(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String to protocol buffer
+ ApiV3.CheckAvailabilityRequest.Builder requestBuilder =
+ ApiV3.CheckAvailabilityRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.CheckAvailabilityRequest checkAvailabilityRequest = 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.CheckAvailabilityResponse response = performCheckAvailability(checkAvailabilityRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to perform availability check
+ private ApiV3.CheckAvailabilityResponse performCheckAvailability(
+ ApiV3.CheckAvailabilityRequest request) {
+
+ // Check availability business logic:
+ // e.g.
+ // ApiV3.Slot requestedSlot = request.getSlot();
+ // int available_spots = ...;
+ // ApiV3.CheckAvailabilityResponse response =
+ // ApiV3.CheckAvailabilityResponse.newBuilder()
+ // .setSlot(requestedSlot)
+ // .setCountAvailable(available_spots)
+ // .build();
+ // return response;
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Path("/CreateBooking")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String createBooking(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String into protocol buffer
+ ApiV3.CreateBookingRequest.Builder requestBuilder = ApiV3.CreateBookingRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.CreateBookingRequest createBookingRequest = 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.CreateBookingResponse response = performCreateBooking(createBookingRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to create a booking based on the request
+ private ApiV3.CreateBookingResponse performCreateBooking(ApiV3.CreateBookingRequest request) {
+
+ // Create booking business logic:
+ // e.g.
+ // ApiV3.Booking createdBooking = ApiV3.Booking.newBuilder()
+ // .setBookingId("sampleBooking1")
+ // .setSlot(request.getSlot())
+ // .setUserInformation(request.getUserInformation())
+ // .setStatus(ApiV3.BookingStatus.CONFIRMED)
+ // .build();
+ //
+ // ApiV3.CreateBookingResponse response = ApiV3.CreateBookingResponse.newBuilder()
+ // .setBooking(createdBooking)
+ // .build();
+ //
+ // Business logic error -> set the BookingFailure in the response
+ // e.g.
+ // BookingServerModel.BookingFailure bookingFailure =
+ // BookingServerModel.BookingFailure.newBuilder()
+ // .setCause(BookingServerModel.BookingFailure.Cause.SLOT_UNAVAILABLE)
+ // .setDescription("slot is not available now")
+ // .build();
+ // BookingServerModel.CreateBookingResponse response =
+ // BookingServerModel.CreateBookingResponse.newBuilder()
+ // .setBookingFailure(bookingFailure).build();
+ //
+ // return response;
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Path("/UpdateBooking")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String updateBooking(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String into protocol buffer
+ ApiV3.UpdateBookingRequest.Builder requestBuilder = ApiV3.UpdateBookingRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.UpdateBookingRequest updateBookingRequest = 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.UpdateBookingResponse response = performUpdateBooking(updateBookingRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to update the booking based on the request
+ private ApiV3.UpdateBookingResponse performUpdateBooking(ApiV3.UpdateBookingRequest request) {
+
+ // Update booking business logic:
+ // e.g.
+ // ApiV3.Booking booking = request.getBooking();
+ // ApiV3.Booking updatedBooking = ...
+ // ApiV3.UpdateBookingResponse response = ApiV3.UpdateBookingResponse.newBuilder()
+ // .setBooking(updatedBooking)
+ // .build();
+ //
+ // Business logic error -> set the BookingFailure in the response
+ // e.g.
+ // BookingServerModel.BookingFailure bookingFailure =
+ // BookingServerModel.BookingFailure.newBuilder()
+ // .setCause(BookingServerModel.BookingFailure.Cause.BOOKING_NOT_CANCELLABLE)
+ // .setDescription("this booking is not cancellable")
+ // .build();
+ // BookingServerModel.CreateBookingResponse response =
+ // BookingServerModel.CreateBookingResponse.newBuilder()
+ // .setBookingFailure(bookingFailure).build();
+ //
+ // return response;
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Path("/GetBookingStatus")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String getBookingStatus(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String into protocol buffer
+ ApiV3.GetBookingStatusRequest.Builder requestBuilder =
+ ApiV3.GetBookingStatusRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.GetBookingStatusRequest getBookingStatusRequest = 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.GetBookingStatusResponse response = performGetBookingStatus(getBookingStatusRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to get the booking status and prepayment status based on
+ // the request
+ private ApiV3.GetBookingStatusResponse performGetBookingStatus(
+ ApiV3.GetBookingStatusRequest request) {
+
+ // Get booking status business logic:
+ // e.g.
+ // String bookingId = request.getBookingId();
+ // ...
+ // ApiV3.GetBookingStatusResponse response = ApiV3.GetBookingStatusResponse.newBuilder()
+ // .setBookingId(bookingId)
+ // .setBookingStatus(ApiV3.BookingStatus.CONFIRMED)
+ // .setPrepaymentStatus(ApiV3.PrepaymentStatus.PREPAYMENT_NOT_PROVIDED)
+ // .build();
+ //
+ // If booking id is not found -> throw new NotFoundException("Booking id not found");
+ //
+ // return response;
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Path("/ListBookings")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String getListBooking(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String into protocol buffer
+ ApiV3.ListBookingsRequest.Builder requestBuilder = ApiV3.ListBookingsRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.ListBookingsRequest listBookingsRequest = 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.ListBookingsResponse response = performGetListBooking(listBookingsRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to look up all bookings with the given userId
+ private ApiV3.ListBookingsResponse performGetListBooking(ApiV3.ListBookingsRequest request) {
+
+ // List bookings business logic:
+ // e.g.
+ // String userId = request.getUserId();
+ // List<ApiV3.Booking> bookings = ...
+ //
+ // ApiV3.ListBookingsResponse response = ApiV3.ListBookingsResponse.newBuilder()
+ // .addAllBookings(bookings)
+ // .build();
+ //
+ // If user id not found -> throw new NotFoundException("User id not found");
+ //
+ // return response;
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Path("/CheckOrderFulfillability")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String checkOrderFulfillability(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String into protocol buffer
+ ApiV3.CheckOrderFulfillabilityRequest.Builder requestBuilder =
+ ApiV3.CheckOrderFulfillabilityRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.CheckOrderFulfillabilityRequest checkOrderFulfillabilityRequest = requestBuilder.build();
+
+ // For 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.CheckOrderFulfillabilityResponse response =
+ performCheckOrderFulfillability(checkOrderFulfillabilityRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to perform order fulfillability check
+ private ApiV3.CheckOrderFulfillabilityResponse performCheckOrderFulfillability(
+ ApiV3.CheckOrderFulfillabilityRequest request) {
+
+ // Check order fulfillability business logic:
+ // e.g.
+ // String merchantId = request.getMerchantId();
+ // List<ApiV3.LineItem> lineItems = request.getItemList();
+ //
+ // List<ApiV3.LineItemFulfillability> itemFulfillabilities =
+ // getLineItemFulfillability(merchantId,lineItems);
+ // ApiV3.OrderFulfillability.OrderFulfillabilityResult result =
+ // getOrderFulfillabilityResult(itemFulfillabilities);
+ //
+ // ApiV3.OrderFulfillability.Builder orderFulfillability =
+ // ApiV3.OrderFulfillability.newBuilder()
+ // .setResult(result);
+ // for (int i = 0; i < itemFulfillabilities.size(); i++) {
+ // orderFulfillability.setItemFulfillability(i, itemFulfillabilities.get(i));
+ // }
+ // ApiV3.Price total = ... // total processing fees & taxes for this order
+ // ApiV3.CheckOrderFulfillabilityResponse response =
+ // ApiV3.CheckOrderFulfillabilityResponse.newBuilder()
+ // .setFulfillability(orderFulfillability.build())
+ // .setFeesAndTaxes(total)
+ // .build();
+ //
+ // return response;
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Path("/CreateOrder")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String createOrder(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String into protocol buffer
+ ApiV3.CreateOrderRequest.Builder requestBuilder = ApiV3.CreateOrderRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.CreateOrderRequest createOrderRequest = requestBuilder.build();
+
+ // For 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.CreateOrderResponse response = performCreateOrder(createOrderRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to create the order based on the request
+ private ApiV3.CreateOrderResponse performCreateOrder(ApiV3.CreateOrderRequest request) {
+
+ // 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)
+ // .build();
+ //
+ // Business logic error -> set the BookingFailure in the response
+ // e.g.
+ // ApiV3.OrderFailure orderFailure = ApiV3.OrderFailure.newBuilder()
+ // .setCause(ApiV3.OrderFailure.Cause.ORDER_UNFULFILLABLE)
+ // .setFulfillability(orderFulfillability...)
+ // .build();
+ // ApiV3.CreateOrderResponse response = ApiV3.CreateOrderResponse.newBuilder()
+ // .setOrderFailure(orderFailure)
+ // .build();
+ //
+ // return response;
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Path("/ListOrders")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public String listOrders(String request) throws InvalidProtocolBufferException {
+
+ // use JsonFormat.Parser to convert Json String into protocol buffer
+ ApiV3.ListOrdersRequest.Builder requestBuilder = ApiV3.ListOrdersRequest.newBuilder();
+ JsonFormat.Parser jsonParser = JsonFormat.parser();
+ jsonParser.merge(request, requestBuilder);
+ ApiV3.ListOrdersRequest listOrdersRequest = requestBuilder.build();
+
+ // For 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.ListOrdersResponse response = getListOrders(listOrdersRequest);
+
+ // use JsonFormat to convert protocol buffer to Json
+ String jsonResponse = jsonPrinter().print(response);
+ return jsonResponse;
+ }
+
+ // TODO(partner): Implement this method to list orders based on user id or order ids
+ private ApiV3.ListOrdersResponse getListOrders(ApiV3.ListOrdersRequest request) {
+
+ // List orders business logic:
+ // e.g.
+ // String userId = request.getUserId();
+ // ApiV3.ListOrdersRequest.OrderIds orderIds = request.getOrderIds();
+ // List<ApiV3.Order> orders = new ArrayList<ApiV3.Order>();
+ // if (userId != null) {
+ // orders = findOrdersByUserId(userId);
+ // } else if (orderIds != null) {
+ // List<String> orderId = orderIds.getOrderIdList();
+ // orders = getOrders(orderId);
+ // } else {
+ // throw new NotFoundException("No userId or orderId matched");
+ // }
+ // ApiV3.ListOrdersResponse.Builder response = ApiV3.ListOrdersResponse.newBuilder();
+ // for (int i = 0; i < orders.size(); i++) {
+ // response.setOrder(i, orders.get(i));
+ // }
+ //
+ // return response.build();
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+}
diff --git a/rest/Error.java b/rest/Error.java
new file mode 100644
index 0000000..d344c4f
--- /dev/null
+++ b/rest/Error.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.partner.mapsbooking.rest;
+
+import com.fasterxml.jackson.annotation.JsonRootName;
+
+/** The JSON object we use to return error message. */
+@JsonRootName(value = "error")
+public class Error {
+ private int statusCode;
+ private String statusDescription;
+ private String errorMessage;
+
+ public Error(int statusCode, String statusDescription, String errorMessage) {
+ this.statusCode = statusCode;
+ this.statusDescription = statusDescription;
+ this.errorMessage = errorMessage;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getStatusDescription() {
+ return statusDescription;
+ }
+
+ public void setStatusDescription(String statusDescription) {
+ this.statusDescription = statusDescription;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+}