Skip to content
Snippets Groups Projects
Unverified Commit d088e6a5 authored by Peter Kurfer's avatar Peter Kurfer
Browse files

Cleanup

parent 2d8585e8
Branches
No related tags found
No related merge requests found
Showing
with 514 additions and 481 deletions
_This is an assignment to the class [Programmieren 3](https://hsro-inf-prg3.github.io) at the [University of Applied Sciences Rosenheim](http://www.fh-rosenheim.de)._ _This is an assignment to the class [Programmieren 3](https://hsro-inf-prg3.github.io) at the [Technical University of Applied Sciences Rosenheim](https://www.th-rosenheim.de)._
# Assignment 11: Futures - CLI variant # Assignment 11: Futures - CLI variant
[![](https://travis-ci.org/hsro-inf-prg3/11-futures-cli.svg?branch=master)](https://travis-ci.org/hsro-inf-prg3/11-futures-cli)
This assignment covers the more advanced multithreading topics _futures_ and _future chaining_. This assignment covers the more advanced multithreading topics _futures_ and _future chaining_.
Futures are a feature of Java 8 and can be compared to the concept of _promises_ in JavaScript. Futures are a feature of Java 8 and can be compared to the concept of _promises_ in JavaScript.
......
...@@ -15,17 +15,17 @@ mainClassName = 'de.thro.inf.prg3.a11.App' ...@@ -15,17 +15,17 @@ mainClassName = 'de.thro.inf.prg3.a11.App'
dependencies { dependencies {
/* Commons Lang3 */ /* Commons Lang3 */
implementation "org.apache.commons:commons-lang3:$commons_lang_version" implementation ("org.apache.commons:commons-lang3:${commons_lang_version}")
/* Retrofit */ /* Retrofit */
implementation "com.squareup.retrofit2:retrofit:$retrofit2_version" implementation("com.squareup.retrofit2:retrofit:${retrofit2_version}")
implementation "com.squareup.retrofit2:converter-gson:$retrofit2_version" implementation("com.squareup.retrofit2:converter-gson:${retrofit2_version}")
/* JUnit 5 */ /* JUnit 5 */
testCompile("org.junit.jupiter:junit-jupiter-api:${junitVersion}") testCompile("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitVersion}") testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
testRuntime("org.junit.jupiter:junit-jupiter-params:${junitVersion}") testRuntime("org.junit.jupiter:junit-jupiter-params:${junitVersion}")
testRuntime("org.apache.logging.log4j:log4j-core:${log4jVersion}") testImplementation("org.apache.logging.log4j:log4j-core:${log4jVersion}")
testRuntime("org.apache.logging.log4j:log4j-jul:${log4jVersion}") testRuntime("org.apache.logging.log4j:log4j-jul:${log4jVersion}")
} }
......
...@@ -101,6 +101,7 @@ public class App { ...@@ -101,6 +101,7 @@ public class App {
/** /**
* Utility method to print menu and read the user selection * Utility method to print menu and read the user selection
*
* @return user selection as MenuSelection * @return user selection as MenuSelection
*/ */
private static MenuSelection menu() { private static MenuSelection menu() {
......
...@@ -19,6 +19,7 @@ public interface OpenMensaAPI { ...@@ -19,6 +19,7 @@ public interface OpenMensaAPI {
/** /**
* Retrieve the first page of all canteens * Retrieve the first page of all canteens
* includes the response wrapper to be able to extract required headers for further pagination handling * includes the response wrapper to be able to extract required headers for further pagination handling
*
* @return first page of canteens wrapped in a response object * @return first page of canteens wrapped in a response object
*/ */
@GET("canteens") @GET("canteens")
...@@ -27,6 +28,7 @@ public interface OpenMensaAPI { ...@@ -27,6 +28,7 @@ public interface OpenMensaAPI {
/** /**
* Retrieve any page of all canteens * Retrieve any page of all canteens
* does not include the response wrapper because the required information should be retrieved before this method is used * does not include the response wrapper because the required information should be retrieved before this method is used
*
* @param pageNumber index of the page to retrieve * @param pageNumber index of the page to retrieve
* @return List of canteens as async future * @return List of canteens as async future
*/ */
...@@ -35,6 +37,7 @@ public interface OpenMensaAPI { ...@@ -35,6 +37,7 @@ public interface OpenMensaAPI {
/** /**
* Get the state of a canteen specified by its id at the specified date * Get the state of a canteen specified by its id at the specified date
*
* @param canteenId id of the canteen * @param canteenId id of the canteen
* @param date date for which the state should be looked up * @param date date for which the state should be looked up
* @return state of the mensa - may be closed or !closed * @return state of the mensa - may be closed or !closed
...@@ -44,6 +47,7 @@ public interface OpenMensaAPI { ...@@ -44,6 +47,7 @@ public interface OpenMensaAPI {
/** /**
* Retrieve the meals for specified date served at canteen specified by its id * Retrieve the meals for specified date served at canteen specified by its id
*
* @param canteenId id of the canteen * @param canteenId id of the canteen
* @param date date for which the meals should be retrieved * @param date date for which the meals should be retrieved
* @return List of meals wrapped as async future * @return List of meals wrapped as async future
......
...@@ -6,6 +6,7 @@ import retrofit2.converter.gson.GsonConverterFactory; ...@@ -6,6 +6,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
/** /**
* OpenMensaAPI service * OpenMensaAPI service
* holds an instance of OpenMensaAPI to avoid multiple instantiations of the API * holds an instance of OpenMensaAPI to avoid multiple instantiations of the API
*
* @author Peter Kurfer * @author Peter Kurfer
*/ */
...@@ -15,11 +16,6 @@ public final class OpenMensaAPIService { ...@@ -15,11 +16,6 @@ public final class OpenMensaAPIService {
private static final OpenMensaAPIService ourInstance = new OpenMensaAPIService(); private static final OpenMensaAPIService ourInstance = new OpenMensaAPIService();
private final OpenMensaAPI openMensaAPI; private final OpenMensaAPI openMensaAPI;
/* singleton accessor */
public static OpenMensaAPIService getInstance() {
return ourInstance;
}
private OpenMensaAPIService() { private OpenMensaAPIService() {
/* Initialize Retrofit */ /* Initialize Retrofit */
...@@ -31,6 +27,11 @@ public final class OpenMensaAPIService { ...@@ -31,6 +27,11 @@ public final class OpenMensaAPIService {
openMensaAPI = retrofit.create(OpenMensaAPI.class); openMensaAPI = retrofit.create(OpenMensaAPI.class);
} }
/* singleton accessor */
public static OpenMensaAPIService getInstance() {
return ourInstance;
}
public OpenMensaAPI getOpenMensaAPI() { public OpenMensaAPI getOpenMensaAPI() {
return openMensaAPI; return openMensaAPI;
} }
......
...@@ -5,6 +5,7 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; ...@@ -5,6 +5,7 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
/** /**
* Data transfer object for a canteen retrieved from the OpenMensaAPI * Data transfer object for a canteen retrieved from the OpenMensaAPI
*
* @author Peter Kurfer * @author Peter Kurfer
*/ */
......
...@@ -8,6 +8,7 @@ import java.util.List; ...@@ -8,6 +8,7 @@ import java.util.List;
/** /**
* Data transfer object for a meal retrieved from the OpenMensaAPI * Data transfer object for a meal retrieved from the OpenMensaAPI
*
* @author Peter Kurfer * @author Peter Kurfer
*/ */
......
...@@ -33,6 +33,28 @@ public final class PageInfo { ...@@ -33,6 +33,28 @@ public final class PageInfo {
this.currentPageIndex = currentPageIndex; this.currentPageIndex = currentPageIndex;
} }
/**
* Factory method to create a PageInfo by parsing the headers of a response which includes the required information
*
* @param apiResponse response object to parse
* @param <T> concrete response type
* @return PageInfo instance - may contain default fallback values see getters
*/
public static <T extends Response<?>> PageInfo extractFromResponse(T apiResponse) {
Headers headers = apiResponse.headers();
int totalPages = extractFromHeaders(headers, TOTAL_PAGES_HEADER, -1);
int totalItemCount = extractFromHeaders(headers, TOTAL_ITEM_COUNT_HEADER, -1);
int itemCountPerPage = extractFromHeaders(headers, ITEM_COUNT_PER_PAGE_HEADER, -1);
int currentPageIndex = extractFromHeaders(headers, CURRENT_PAGE_INDEX_HEADER, -1);
return new PageInfo(totalPages, totalItemCount, itemCountPerPage, currentPageIndex);
}
private static int extractFromHeaders(Headers headers, String headerName, int fallback) {
String headerValue = headers.get(headerName);
return headerValue == null ? fallback : Integer.parseInt(headerValue);
}
/** /**
* @return total count of pages or -1 if required header was not present * @return total count of pages or -1 if required header was not present
*/ */
...@@ -60,26 +82,4 @@ public final class PageInfo { ...@@ -60,26 +82,4 @@ public final class PageInfo {
public int getCurrentPageIndex() { public int getCurrentPageIndex() {
return currentPageIndex; return currentPageIndex;
} }
/**
* Factory method to create a PageInfo by parsing the headers of a response which includes the required information
*
* @param apiResponse response object to parse
* @param <T> concrete response type
* @return PageInfo instance - may contain default fallback values see getters
*/
public static <T extends Response<?>> PageInfo extractFromResponse(T apiResponse) {
Headers headers = apiResponse.headers();
int totalPages = extractFromHeaders(headers, TOTAL_PAGES_HEADER, -1);
int totalItemCount = extractFromHeaders(headers, TOTAL_ITEM_COUNT_HEADER, -1);
int itemCountPerPage = extractFromHeaders(headers, ITEM_COUNT_PER_PAGE_HEADER, -1);
int currentPageIndex = extractFromHeaders(headers, CURRENT_PAGE_INDEX_HEADER, -1);
return new PageInfo(totalPages, totalItemCount, itemCountPerPage, currentPageIndex);
}
private static int extractFromHeaders(Headers headers, String headerName, int fallback) {
String headerValue = headers.get(headerName);
return headerValue == null ? fallback : Integer.parseInt(headerValue);
}
} }
...@@ -6,6 +6,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder; ...@@ -6,6 +6,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
/** /**
* Data transfer object for a state of a canteen retrieved from the OpenMensaAPI * Data transfer object for a state of a canteen retrieved from the OpenMensaAPI
*
* @author Peter Kurfer * @author Peter Kurfer
*/ */
......
...@@ -3,7 +3,10 @@ package de.thro.inf.prg3.a11.tests; ...@@ -3,7 +3,10 @@ package de.thro.inf.prg3.a11.tests;
import de.thro.inf.prg3.a11.openmensa.OpenMensaAPI; import de.thro.inf.prg3.a11.openmensa.OpenMensaAPI;
import de.thro.inf.prg3.a11.openmensa.OpenMensaAPIService; import de.thro.inf.prg3.a11.openmensa.OpenMensaAPIService;
import de.thro.inf.prg3.a11.openmensa.model.PageInfo; import de.thro.inf.prg3.a11.openmensa.model.PageInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import retrofit2.HttpException; import retrofit2.HttpException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
...@@ -16,18 +19,22 @@ import static org.junit.jupiter.api.Assertions.*; ...@@ -16,18 +19,22 @@ import static org.junit.jupiter.api.Assertions.*;
/** /**
* @author Peter Kurfer * @author Peter Kurfer
*/ */
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
class OpenMensaApiTests { class OpenMensaApiTests {
private static final Logger logger = LogManager.getLogger(OpenMensaApiTests.class);
private static final int THRO_MENSA_ID = 229; private static final int THRO_MENSA_ID = 229;
private static final String OPEN_MENSA_DATE_FORMAT = "yyyy-MM-dd"; private static final String OPEN_MENSA_DATE_FORMAT = "yyyy-MM-dd";
private final SimpleDateFormat dateFormat; private static final SimpleDateFormat dateFormat = new SimpleDateFormat(OPEN_MENSA_DATE_FORMAT, Locale.getDefault());
private final OpenMensaAPI openMensaAPI; private final OpenMensaAPI openMensaAPI;
private final Calendar calendar; private final Calendar calendar;
OpenMensaApiTests() { OpenMensaApiTests() {
dateFormat = new SimpleDateFormat(OPEN_MENSA_DATE_FORMAT, Locale.getDefault()); openMensaAPI = OpenMensaAPIService
openMensaAPI = OpenMensaAPIService.getInstance().getOpenMensaAPI(); .getInstance()
.getOpenMensaAPI();
calendar = Calendar.getInstance(); calendar = Calendar.getInstance();
} }
...@@ -40,7 +47,7 @@ class OpenMensaApiTests { ...@@ -40,7 +47,7 @@ class OpenMensaApiTests {
assertNotEquals(0, canteensResponse.body().size()); assertNotEquals(0, canteensResponse.body().size());
for (var c : canteensResponse.body()) { for (var c : canteensResponse.body()) {
System.out.println(c.getName()); logger.info(c.getName());
} }
} }
...@@ -60,11 +67,13 @@ class OpenMensaApiTests { ...@@ -60,11 +67,13 @@ class OpenMensaApiTests {
@Test @Test
void testGetCanteenState() throws InterruptedException { void testGetCanteenState() throws InterruptedException {
try { try {
final var mensaState = openMensaAPI.getCanteenState(THRO_MENSA_ID, dateFormat.format(calendar.getTime())).get(); var date = dateFormat.format(calendar.getTime());
logger.info("Fetching canteen state for date {}", date);
final var mensaState = openMensaAPI.getCanteenState(THRO_MENSA_ID, date).get();
assertNotNull(mensaState); assertNotNull(mensaState);
} catch (ExecutionException e) { } catch (ExecutionException e) {
if (e.getCause() instanceof HttpException) { if (e.getCause() instanceof HttpException) {
System.out.println(String.format("HTTP error: %s", e.getCause().getMessage())); logger.info("HTTP error: {}", e.getCause().getMessage());
} }
} }
} }
......
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="all">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment