Created
August 19, 2019 09:20
-
-
Save uptown/7b13163031c296b4da6db66c0c3270af to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package co.halfz.commons.http; | |
import org.apache.http.HttpHost; | |
import org.apache.http.HttpRequest; | |
import org.apache.http.HttpResponse; | |
import org.apache.http.client.methods.HttpUriRequest; | |
import org.apache.http.nio.protocol.HttpAsyncRequestProducer; | |
import org.apache.http.nio.protocol.HttpAsyncResponseConsumer; | |
import org.apache.http.protocol.HttpContext; | |
import java.util.concurrent.CompletionStage; | |
public interface CompletableHttpAsyncClient { | |
<T> CompletionStage<T> execute(HttpAsyncRequestProducer httpAsyncRequestProducer, | |
HttpAsyncResponseConsumer<T> httpAsyncResponseConsumer, HttpContext httpContext); | |
<T> CompletionStage<T> execute(HttpAsyncRequestProducer httpAsyncRequestProducer, | |
HttpAsyncResponseConsumer<T> httpAsyncResponseConsumer); | |
CompletionStage<HttpResponse> execute(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext); | |
CompletionStage<HttpResponse> execute(HttpHost httpHost, HttpRequest httpRequest); | |
CompletionStage<HttpResponse> execute(HttpUriRequest httpUriRequest, HttpContext httpContext); | |
CompletionStage<HttpResponse> execute(HttpUriRequest httpUriRequest); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package co.halfz.commons.http; | |
import org.apache.http.HttpHost; | |
import org.apache.http.HttpRequest; | |
import org.apache.http.HttpResponse; | |
import org.apache.http.client.methods.HttpUriRequest; | |
import org.apache.http.concurrent.FutureCallback; | |
import org.apache.http.nio.client.HttpAsyncClient; | |
import org.apache.http.nio.protocol.HttpAsyncRequestProducer; | |
import org.apache.http.nio.protocol.HttpAsyncResponseConsumer; | |
import org.apache.http.protocol.HttpContext; | |
import java.util.concurrent.CompletableFuture; | |
import java.util.concurrent.CompletionStage; | |
import java.util.function.Consumer; | |
public class CompletableHttpAsyncClientImpl implements CompletableHttpAsyncClient { | |
private final HttpAsyncClient httpAsyncClient; | |
public CompletableHttpAsyncClientImpl(HttpAsyncClient httpAsyncClient) { | |
this.httpAsyncClient = httpAsyncClient; | |
} | |
public <T> CompletionStage<T> execute(HttpAsyncRequestProducer httpAsyncRequestProducer, HttpAsyncResponseConsumer<T> httpAsyncResponseConsumer, HttpContext httpContext) { | |
return toCompletableFuture(fc -> httpAsyncClient.execute(httpAsyncRequestProducer, httpAsyncResponseConsumer, httpContext, fc)); | |
} | |
public <T> CompletionStage<T> execute(HttpAsyncRequestProducer httpAsyncRequestProducer, HttpAsyncResponseConsumer<T> httpAsyncResponseConsumer) { | |
return toCompletableFuture(fc -> httpAsyncClient.execute(httpAsyncRequestProducer, httpAsyncResponseConsumer, fc)); | |
} | |
public CompletionStage<HttpResponse> execute(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext) { | |
return toCompletableFuture(fc -> httpAsyncClient.execute(httpHost, httpRequest, httpContext, fc)); | |
} | |
public CompletionStage<HttpResponse> execute(HttpHost httpHost, HttpRequest httpRequest) { | |
return toCompletableFuture(fc -> httpAsyncClient.execute(httpHost, httpRequest, fc)); | |
} | |
public CompletionStage<HttpResponse> execute(HttpUriRequest httpUriRequest, HttpContext httpContext) { | |
return toCompletableFuture(fc -> httpAsyncClient.execute(httpUriRequest, httpContext, fc)); | |
} | |
public CompletionStage<HttpResponse> execute(HttpUriRequest httpUriRequest) { | |
return toCompletableFuture(fc -> httpAsyncClient.execute(httpUriRequest, fc)); | |
} | |
private static <T> CompletionStage<T> toCompletableFuture(Consumer<FutureCallback<T>> c) { | |
CompletableFuture<T> promise = new CompletableFuture<>(); | |
c.accept(new FutureCallback<T>() { | |
@Override | |
public void completed(T t) { | |
promise.complete(t); | |
} | |
@Override | |
public void failed(Exception e) { | |
promise.completeExceptionally(e); | |
} | |
@Override | |
public void cancelled() { | |
promise.cancel(true); | |
} | |
}); | |
return promise; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package co.halfz.holiday; | |
import co.halfz.commons.base.BaseObject; | |
import lombok.AllArgsConstructor; | |
import lombok.Getter; | |
import lombok.NoArgsConstructor; | |
import lombok.Setter; | |
import java.time.LocalDate; | |
@Getter | |
@Setter | |
@AllArgsConstructor(staticName = "of") | |
@NoArgsConstructor | |
public class Holiday extends BaseObject { | |
private String name; | |
private LocalDate date; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package co.halfz.holiday; | |
import co.halfz.commons.http.CompletableHttpAsyncClient; | |
import org.apache.commons.io.IOUtils; | |
import org.apache.http.client.methods.HttpGet; | |
import org.jsoup.Jsoup; | |
import org.jsoup.nodes.Document; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.stereotype.Service; | |
import org.springframework.web.util.UriComponentsBuilder; | |
import java.io.IOException; | |
import java.nio.charset.StandardCharsets; | |
import java.time.LocalDate; | |
import java.time.format.DateTimeFormatter; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.concurrent.CompletionException; | |
import java.util.concurrent.CompletionStage; | |
import java.util.stream.Collectors; | |
@Service | |
public class HolidayService { | |
private final static String SERVICE_KEY = "SERVICE_KEY"; | |
private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); | |
@Autowired | |
private CompletableHttpAsyncClient asyncClient; | |
public Holiday findHoliday(LocalDate date) { | |
return findHolidays(date.getYear()).stream() | |
.filter(holiday -> holiday.getDate() | |
.equals(date)) | |
.findAny() | |
.orElse(null); | |
} | |
public List<Holiday> findHolidays(LocalDate fromDate, LocalDate endDate) { | |
if (fromDate.isAfter(endDate)) | |
return Collections.emptyList(); | |
List<Holiday> holidays = findHolidays(fromDate.getYear()); | |
if (fromDate.getYear() != endDate.getYear()) { | |
holidays = new ArrayList<>(holidays); | |
holidays.addAll(findHolidays(endDate.getYear())); | |
} | |
return holidays.stream() | |
.filter(holiday -> holiday.getDate() | |
.isBefore(endDate.plusDays(1)) && holiday.getDate() | |
.isAfter(fromDate.minusDays(1))) | |
.collect(Collectors.toList()); | |
} | |
@SuppressWarnings("unchecked") | |
public List<Holiday> findHolidays(int year) { | |
List<CompletionStage<List<Holiday>>> holidays = new ArrayList<>(); | |
for (int i = 1; i < 13; i++) { | |
holidays.add(findHolidays(year, i)); | |
} | |
return holidays.stream() | |
.flatMap(r -> r.toCompletableFuture() | |
.join() | |
.stream()) | |
.collect(Collectors.toList()); | |
} | |
public boolean isHoliday(LocalDate date) { | |
return findHolidays(date.getYear()).stream() | |
.anyMatch(holiday -> holiday.getDate() | |
.equals(date)); | |
} | |
private CompletionStage<List<Holiday>> findHolidays(int year, int month) { | |
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl( | |
"http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getRestDeInfo"); | |
uriComponentsBuilder.queryParam("ServiceKey", SERVICE_KEY); | |
uriComponentsBuilder.queryParam("solYear", year); | |
uriComponentsBuilder.queryParam("solMonth", String.format("%02d", month)); | |
HttpGet httpGet = new HttpGet(uriComponentsBuilder.toUriString()); | |
return asyncClient.execute(httpGet) | |
.thenApply(response -> { | |
try { | |
String ret = IOUtils.toString(response.getEntity() | |
.getContent(), StandardCharsets.UTF_8); | |
Document parse = Jsoup.parse(ret); | |
return parse.select("items > item") | |
.stream() | |
.map(element -> { | |
String datename = element.getElementsByTag("datename") | |
.first() | |
.textNodes() | |
.get(0) | |
.text(); | |
String locdate = element.getElementsByTag("locdate") | |
.text(); | |
return Holiday.of(datename, LocalDate.parse(locdate, formatter)); | |
}) | |
.collect(Collectors.toList()); | |
} catch (IOException e) { | |
throw new CompletionException(e); | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment