208 lines
7.8 KiB
Java
208 lines
7.8 KiB
Java
package client.utils;
|
|
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import commons.Recipe;
|
|
import commons.RecipeIngredient;
|
|
import jakarta.ws.rs.ProcessingException;
|
|
import jakarta.ws.rs.client.ClientBuilder;
|
|
import org.glassfish.jersey.client.ClientConfig;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.net.ConnectException;
|
|
import java.net.URI;
|
|
import java.net.http.HttpClient;
|
|
import java.net.http.HttpRequest;
|
|
import java.net.http.HttpResponse;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
|
|
|
|
|
|
public class ServerUtils {
|
|
private static final String SERVER = "http://localhost:8080/api";
|
|
private final HttpClient client;
|
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
private final int statusOK = 200;
|
|
|
|
public ServerUtils() {
|
|
client = HttpClient.newHttpClient();
|
|
}
|
|
|
|
/**
|
|
* Gets all the recipes from the backend.
|
|
* @return a JSON string with all the recipes
|
|
*/
|
|
public List<Recipe> getRecipes() throws IOException, InterruptedException {
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(SERVER + "/recipes"))
|
|
.GET()
|
|
.build();
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
if(response.statusCode() != statusOK){
|
|
throw new IOException("No recipe to get. Server responds with " + response.body());
|
|
}
|
|
|
|
|
|
return objectMapper.readValue(response.body(), new TypeReference<List<Recipe>>() {
|
|
});// JSON string-> List<Recipe> (Jackson)
|
|
}
|
|
|
|
public List<Recipe> getRecipesFiltered(String filter) throws IOException, InterruptedException {
|
|
// TODO: implement filtering on server side
|
|
return this.getRecipes();
|
|
}
|
|
|
|
/**
|
|
* Gets a single recipe based on its id.
|
|
* @param id every recipe has it's unique id
|
|
* @return a singe recipe with the given id
|
|
*/
|
|
public Recipe findId(long id) throws IOException, InterruptedException {
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(SERVER +"/recipe/" + id))
|
|
.GET()
|
|
.build();
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
if(response.statusCode() != statusOK){
|
|
throw new IOException("failed finding recipe with id: "+ id + " body: " + response.body());
|
|
}
|
|
|
|
return objectMapper.readValue(response.body(),Recipe.class);
|
|
}
|
|
|
|
/**
|
|
* Adds a recipe to the backend.
|
|
* @param newRecipe the recipe to be added
|
|
* @return a recipe
|
|
*/
|
|
public Recipe addRecipe(Recipe newRecipe) throws IOException, InterruptedException {
|
|
//Make sure the name of the newRecipe is unique
|
|
List<Recipe> allRecipes = getRecipes();
|
|
|
|
|
|
int version = 1;
|
|
String originalName = newRecipe.getName();
|
|
while (allRecipes.stream().anyMatch(r -> r.getName().equals(newRecipe.getName()))) {
|
|
String newName = originalName + "(" + version++ + ")";
|
|
newRecipe.setName(newName);
|
|
}
|
|
|
|
String json = objectMapper.writeValueAsString(newRecipe);
|
|
|
|
//Recipe to backend
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(SERVER + "/recipe/new"))
|
|
.header("Content-Type", "application/json")
|
|
.PUT(HttpRequest.BodyPublishers.ofString(json))
|
|
.build();
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
if(response.statusCode() != statusOK){
|
|
throw new IOException("Failed to add Recipe: " + newRecipe.toDetailedString() + "body: " + response.body());
|
|
}
|
|
|
|
return objectMapper.readValue(response.body(),Recipe.class);
|
|
}
|
|
|
|
/**
|
|
* Deletes a recipe.
|
|
* @param id the recipe that get deleted
|
|
*/
|
|
public void deleteRecipe(long id) throws IOException, InterruptedException {
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(SERVER + "/recipe/" + id))
|
|
.DELETE()
|
|
.build();
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
if(response.statusCode() != statusOK){
|
|
throw new IOException("Failed removing recipe with id: " + id + "body: " + response.body());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clones a recipe.
|
|
* @param id the id of the recipe to be cloned
|
|
* @return a duplicated recipe of the given recipe
|
|
*/
|
|
public Recipe cloneRecipe(long id) throws IOException, InterruptedException {
|
|
//Get the recipe
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(SERVER + "/recipe/" + id))
|
|
.GET() //Needs to be changed to POST() when api is changed
|
|
.build();
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
//200 is the status code for success, other codes can mean there is no recipe to clone
|
|
if(response.statusCode() != statusOK){
|
|
throw new IOException("Failed to get recipe to clone with id: " + id + "body: " + response.body());
|
|
}
|
|
// recipe exists so you can make a "new" recipe aka the clone
|
|
Recipe recipe = objectMapper.readValue(response.body(), Recipe.class);
|
|
|
|
recipe.setId(null); // otherwise the id is the same as the original, and that's wrong
|
|
// now that each recipeIngredient has its own ID in the database,
|
|
// we set that to null too to force a new persist value on the server
|
|
recipe.getIngredients().forEach(ingredient -> ingredient.setId(null));
|
|
return addRecipe(recipe);
|
|
}
|
|
|
|
public boolean isServerAvailable() {
|
|
try {
|
|
ClientBuilder.newClient(new ClientConfig()) //
|
|
.target(SERVER) //
|
|
.request(APPLICATION_JSON) //
|
|
.get();
|
|
} catch (ProcessingException e) {
|
|
if (e.getCause() instanceof ConnectException) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void addRecipeName(String name) throws IOException, InterruptedException {
|
|
Recipe newRecipe = new Recipe();
|
|
newRecipe.setName(name);
|
|
addRecipe(newRecipe);
|
|
|
|
}
|
|
|
|
public void addRecipeIngredient(Recipe recipe, RecipeIngredient ingredient) throws IOException, InterruptedException {
|
|
List<RecipeIngredient> ingredients = new ArrayList<>(recipe.getIngredients());
|
|
ingredients.add(ingredient);
|
|
recipe.setIngredients(ingredients);
|
|
|
|
updateRecipe(recipe);
|
|
}
|
|
|
|
public void updateRecipe(Recipe recipe) throws IOException, InterruptedException {
|
|
String json = objectMapper.writeValueAsString(recipe);
|
|
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(SERVER + "/recipe/" + recipe.getId()))
|
|
.header("Content-Type", "application/json")
|
|
.POST(HttpRequest.BodyPublishers.ofString((json))) // Needs to be changed to PUT() when api changed
|
|
.build();
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
if(response.statusCode() != statusOK){
|
|
throw new IOException("Failed to update recipe: " + recipe.toDetailedString() + "body: " + response.body());
|
|
}
|
|
|
|
objectMapper.readValue(response.body(), Recipe.class);
|
|
}
|
|
|
|
public void addRecipeStep(Recipe recipe, String preparationStep) throws IOException, InterruptedException {
|
|
List<String> preparationSteps = new ArrayList<>(recipe.getPreparationSteps());
|
|
preparationSteps.add(preparationStep);
|
|
recipe.setPreparationSteps(preparationSteps);
|
|
|
|
updateRecipe(recipe);
|
|
}
|
|
}
|