Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit cebbede

Browse files
Rest apis with gson and rest GET call example (#14)
* add ReentrantReadWriteLock on shared state * gson parsing and GET api call example
1 parent 893897a commit cebbede

File tree

5 files changed

+200
-0
lines changed

5 files changed

+200
-0
lines changed

‎REST/Hotel.java‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import com.google.gson.annotations.SerializedName;
2+
/*
3+
* Entity class to represent City
4+
* with natural ordering of rating when compared
5+
*/
6+
7+
public class Hotel implements Comparable<Hotel> {
8+
// inner class for rating
9+
class UserRating implements Comparable<UserRating>{
10+
@SerializedName("average_rating")
11+
double averageRating;
12+
int votes;
13+
14+
public UserRating(double averageRating, int votes){
15+
this.averageRating = averageRating;
16+
this.votes = votes;
17+
}
18+
19+
@Override
20+
public int compareTo(UserRating other){
21+
if(this.averageRating == other.averageRating){
22+
return Integer.compare(this.votes, other.votes);
23+
}
24+
return Double.compare(this.averageRating, other.averageRating);
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return "{averageRating:" + this.averageRating + ",votes:" + votes + "}";
30+
}
31+
}
32+
33+
String id;
34+
String city;
35+
String name;
36+
37+
@SerializedName("estimated_cost")
38+
double estimatedCost;
39+
40+
@SerializedName("user_rating")
41+
UserRating userRating;
42+
43+
public Hotel(String id, String name, String city, UserRating rating) {
44+
this.id = id;
45+
this.name = name;
46+
this.city = city;
47+
this.userRating = rating;
48+
}
49+
50+
@Override
51+
public int compareTo(Hotel other){
52+
if(this.estimatedCost == other.estimatedCost){
53+
return this.userRating.compareTo(userRating);
54+
}
55+
return Double.compare(this.estimatedCost, other.estimatedCost);
56+
}
57+
58+
@Override
59+
public String toString() {
60+
return "\nHotel id:" + id + ",name:" + name + ",city:"+ city + ",estimatedCost:" + estimatedCost
61+
+ ",userRating:" + userRating;
62+
}
63+
}

‎REST/HotelPage.java‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import com.google.gson.annotations.SerializedName;
2+
import java.util.List;
3+
/**
4+
* Entity to hold per page api response from GET hotels API calls
5+
*/
6+
public class HotelPage {
7+
8+
int page;
9+
10+
@SerializedName("per_page")
11+
int perPage;
12+
13+
int total;
14+
15+
@SerializedName("total_pages")
16+
int totalPages;
17+
18+
List<Hotel> data;
19+
20+
@Override
21+
public String toString() {
22+
return "\nHotelPage page:" + page + ",per_page:" + perPage + ",total:" + total + ",total_pages:" + totalPages + ",data:" + data;
23+
}
24+
}

‎REST/READ.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Compile and Run instruction from current directory:
2+
<code>
3+
javac -cp lib/gson-2.2.2.jar:. RestWithGson.java
4+
java -cp lib/gson-2.2.2.jar:. RestWithGson
5+
</code>

‎REST/RestWithGson.java‎

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import java.io.BufferedReader;
2+
import java.io.InputStreamReader;
3+
import java.net.HttpURLConnection;
4+
import java.net.URL;
5+
import java.util.PriorityQueue;
6+
import java.util.List;
7+
import java.util.LinkedList;
8+
import java.util.UUID;
9+
10+
import com.google.gson.Gson;
11+
12+
/*
13+
* GET API: https://jsonmock.hackerrank.com/api/food_outlets?page={page_no}
14+
*/
15+
16+
public class RestWithGson {
17+
final String BASE_URL = "https://jsonmock.hackerrank.com";
18+
final int TIMEOUT_MILLISEC = (int)1e3; // 1 sec timeout
19+
20+
PriorityQueue<Hotel> getTopHotels(int top){
21+
PriorityQueue <Hotel> topHotels = new PriorityQueue<Hotel>();
22+
// MAX Bounded Queue of Size `top`
23+
int currentPage = 0;
24+
int maxPages = 1;
25+
// todo: currently flow is sequential one by one page
26+
// we can spawn new thread pool of size K to get data to reduce overall network time
27+
// to MAX_PAGES/K
28+
while(currentPage < maxPages){
29+
HotelPage currentSetOfHotels = getCurrentPage(currentPage);
30+
maxPages = currentSetOfHotels.totalPages;
31+
if(currentSetOfHotels.data != null && currentSetOfHotels.data.size() == 0){
32+
System.out.println("empty data\n"); //todo: retry to get current page with exponential backoff
33+
break;
34+
}
35+
add(currentSetOfHotels.data, topHotels, top);
36+
currentPage++;
37+
}
38+
return topHotels;
39+
}
40+
41+
// make a network get call to get the current page data
42+
// and add it to queue as rolling window
43+
HotelPage getCurrentPage(int page){
44+
String route = BASE_URL + "/api/food_outlets?page=" + page;
45+
try {
46+
URL url = new URL(route);
47+
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
48+
connection.setRequestMethod("GET"); // anyway default it get but specifying it improves
49+
// code readibility
50+
connection.setConnectTimeout(TIMEOUT_MILLISEC);
51+
if(connection.getResponseCode() == 200){
52+
BufferedReader response = new BufferedReader(new InputStreamReader(connection.getInputStream()));
53+
StringBuilder responseBuilder = new StringBuilder();
54+
String line = null;
55+
while((line = response.readLine()) != null){
56+
responseBuilder.append(line);
57+
}
58+
return parseStringToCities(responseBuilder.toString());
59+
}
60+
} catch (Exception exception){
61+
System.out.println(exception);
62+
return null;
63+
}
64+
return null;
65+
}
66+
67+
// deserialize text to object
68+
HotelPage parseStringToCities(String responseText){
69+
// using gson to cast into
70+
Gson deserializer = new Gson();
71+
return deserializer.fromJson(responseText, HotelPage.class);
72+
}
73+
74+
// adding to bounded queue
75+
// add time: O(log `top`), space: O(top)
76+
void add(List<Hotel> currentSetOfHotels, PriorityQueue<Hotel> topHotels, int top) {
77+
for(Hotel hotel: currentSetOfHotels){
78+
// to ensure heap having at least `top` elements
79+
if(topHotels.size() < top){
80+
topHotels.add(hotel);
81+
continue;
82+
}
83+
// re-balancing heap in log n
84+
topHotels.add(hotel);
85+
topHotels.poll(); // todo: we can maintain maxHeap instad of minHeap
86+
// and we can check top element in O(1) and avoid everytime rebalancing heap
87+
// although it does not impact time complexity but a very good perf improvement
88+
}
89+
}
90+
91+
void run()throws Exception{
92+
PriorityQueue<Hotel> topHotels = getTopHotels(10);
93+
while(!topHotels.isEmpty()) {
94+
System.out.println("top hotel:" + topHotels.poll());
95+
}
96+
}
97+
98+
public static void main(String[] args) throws Exception{
99+
RestWithGson driver = new RestWithGson();
100+
driver.run();
101+
driver.closeResources();
102+
}
103+
104+
private void closeResources(){
105+
System.out.flush();
106+
// clear up class level resources like io, dbconnections etc.
107+
}
108+
}

‎REST/lib/gson-2.2.2.jar‎

185 KB
Binary file not shown.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /