diff --git a/pom.xml b/pom.xml
index 70ad326..f2f1949 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,10 @@
spring-boot-starter-test
test
+
+ org.springframework.data
+ spring-data-commons
+
org.springframework.modulith
spring-modulith-starter-test
@@ -82,10 +86,6 @@
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
-
- org.springframework.boot
- spring-boot-starter-hateoas
-
com.github.ben-manes.caffeine
caffeine
diff --git a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/controllers/TimezoneController.java b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/controllers/TimezoneController.java
index 2d3d2de..24d75a8 100644
--- a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/controllers/TimezoneController.java
+++ b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/controllers/TimezoneController.java
@@ -1,19 +1,18 @@
package dev.mars3142.fhq.timezone_service.timezone.controllers;
-import static org.springframework.beans.support.PagedListHolder.DEFAULT_PAGE_SIZE;
-import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
-
-import dev.mars3142.fhq.timezone_service.timezone.domain.model.response.LocationResponse;
import dev.mars3142.fhq.timezone_service.timezone.domain.model.response.TimezoneResponse;
import dev.mars3142.fhq.timezone_service.timezone.service.TimezoneService;
import lombok.RequiredArgsConstructor;
import lombok.val;
-import org.springdoc.core.converters.models.Pageable;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@@ -35,18 +34,20 @@ public class TimezoneController {
val response = new TimezoneResponse();
response.setTimezone(timezoneInfo.timezone());
response.setPosix_tz(posix);
- response.add(linkTo(TimezoneController.class).slash(ip).withSelfRel());
return response;
}
@GetMapping("{area}")
@ResponseStatus(HttpStatus.OK)
- public LocationResponse getLocations(@PathVariable String area) {
- val locations = timeZoneService.getLocations(area);
- val result = new LocationResponse();
- result.setLocations(locations);
- result.add(linkTo(TimezoneController.class).slash(area).withSelfRel());
- return result;
+ public Page getLocations(@PathVariable String area,
+ @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize,
+ @RequestParam(value = "page", required = false, defaultValue = "0") int page,
+ @RequestParam(value = "direction", required = false) String direction) {
+ var pageRequest = PageRequest.of(page, pageSize);
+ if (direction != null && !direction.isEmpty()) {
+ pageRequest = PageRequest.of(page, pageSize, Direction.fromString(direction), "location");
+ }
+ return timeZoneService.getPagedLocations(area, pageRequest);
}
@GetMapping("{area}/{location}")
@@ -57,7 +58,6 @@ public class TimezoneController {
val response = new TimezoneResponse();
response.setTimezone(timezone);
response.setPosix_tz(posix);
- response.add(linkTo(TimezoneController.class).slash(area).slash(location).withSelfRel());
return response;
}
}
diff --git a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/domain/model/response/LocationResponse.java b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/domain/model/response/LocationResponse.java
deleted file mode 100644
index 040ee60..0000000
--- a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/domain/model/response/LocationResponse.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package dev.mars3142.fhq.timezone_service.timezone.domain.model.response;
-
-import java.util.List;
-import lombok.Getter;
-import org.springframework.hateoas.RepresentationModel;
-
-@Getter
-public class LocationResponse extends RepresentationModel {
-
- private int count;
- private List locations;
-
- public void setLocations(List locations) {
- this.count = locations.size();
- this.locations = locations;
- }
-}
diff --git a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/domain/model/response/TimezoneResponse.java b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/domain/model/response/TimezoneResponse.java
index 026d48f..b5329f6 100644
--- a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/domain/model/response/TimezoneResponse.java
+++ b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/domain/model/response/TimezoneResponse.java
@@ -2,11 +2,10 @@ package dev.mars3142.fhq.timezone_service.timezone.domain.model.response;
import lombok.Getter;
import lombok.Setter;
-import org.springframework.hateoas.RepresentationModel;
@Getter
@Setter
-public class TimezoneResponse extends RepresentationModel {
+public class TimezoneResponse {
private String timezone;
private String posix_tz;
diff --git a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/TimezoneService.java b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/TimezoneService.java
index 6b0556b..b22f0b5 100644
--- a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/TimezoneService.java
+++ b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/TimezoneService.java
@@ -2,7 +2,8 @@ package dev.mars3142.fhq.timezone_service.timezone.service;
import dev.mars3142.fhq.timezone_service.timezone.domain.entities.response.IPApiResponse;
import dev.mars3142.fhq.timezone_service.timezone.domain.entities.response.TimeApiTimezoneZoneResponse;
-import java.util.List;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
public interface TimezoneService {
@@ -14,5 +15,5 @@ public interface TimezoneService {
String getPosixTimeZone(String timezone);
- List getLocations(String area);
+ Page getPagedLocations(String area, PageRequest pageRequest);
}
diff --git a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImpl.java b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImpl.java
index a1519c1..e9de16c 100644
--- a/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImpl.java
+++ b/src/main/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImpl.java
@@ -15,6 +15,9 @@ import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
@@ -48,18 +51,18 @@ public class TimezoneServiceImpl implements TimezoneService {
@Override
@Cacheable(value = "TZInfoByIp", key = "{#ip}")
public IPApiResponse getTimeZoneInfoByIp(String ip) {
- return restClient
- .get()
- .uri(builder -> builder
- .scheme("http")
- .host("ip-api.com")
- .path("json/" + ip)
- .build())
- .retrieve()
- .onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
- throw new NotFoundException();
- })
- .body(IPApiResponse.class);
+ return restClient
+ .get()
+ .uri(builder -> builder
+ .scheme("http")
+ .host("ip-api.com")
+ .path("json/" + ip)
+ .build())
+ .retrieve()
+ .onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
+ throw new NotFoundException();
+ })
+ .body(IPApiResponse.class);
}
@Override
@@ -97,19 +100,41 @@ public class TimezoneServiceImpl implements TimezoneService {
}
@Override
- @Cacheable(value = "locations", key = "{#area}")
- public List getLocations(String area) {
+ @Cacheable(value = "locations", key = "{#area, #pageRequest}")
+ public Page getPagedLocations(String area, PageRequest pageRequest) {
val directory = new File("/usr/share/zoneinfo/" + area);
if (!directory.exists()) {
throw new NotFoundException();
}
- return Stream.of(Objects.requireNonNull(directory.listFiles()))
+ return toPage(Stream.of(Objects.requireNonNull(directory.listFiles()))
.filter(file -> !file.isDirectory())
.map(file -> {
val path = file.getPath().split("/");
return path[path.length - 2] + "/" + path[path.length - 1];
})
- .sorted()
- .toList();
+ .toList(), pageRequest);
+ }
+
+ Page toPage(List list, PageRequest pageRequest) {
+ val pageSize = pageRequest.getPageSize();
+ val pageNumber = pageRequest.getPageNumber();
+ val totalPages = list.size() / pageSize;
+
+ int max = pageNumber >= totalPages ? list.size() : pageSize * (pageNumber + 1);
+ int min = pageNumber > totalPages ? max : pageSize * pageNumber;
+
+ var content = list.stream().sorted((left, right) -> {
+ if (!pageRequest.getSort().isSorted()) {
+ return 0;
+ }
+
+ if (Objects.requireNonNull(pageRequest.getSort().getOrderFor("location")).isAscending()) {
+ return left.compareTo(right);
+ } else {
+ return right.compareTo(left);
+ }
+ }
+ );
+ return new PageImpl<>(content.toList().subList(min, max), pageRequest, list.size());
}
}
diff --git a/src/test/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImplTest.java b/src/test/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImplTest.java
index a5186f2..2f35f0b 100644
--- a/src/test/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImplTest.java
+++ b/src/test/java/dev/mars3142/fhq/timezone_service/timezone/service/impl/TimezoneServiceImplTest.java
@@ -59,6 +59,6 @@ class TimezoneServiceImplTest {
}
@Test
- void getLocations() {
+ void getPagedLocations() {
}
}