Skip to content

Commit

Permalink
As a user I can import recipes with their nutritional information #188
Browse files Browse the repository at this point in the history
Also added user agent to Jsoup request.
  • Loading branch information
flauschtrud committed Dec 14, 2024
1 parent 8dd615c commit c8e8145
Show file tree
Hide file tree
Showing 7 changed files with 600 additions and 529 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.flauschcode.broccoli.recipe.importing;

import android.app.Application;
import android.util.Log;

import com.flauschcode.broccoli.R;
import com.flauschcode.broccoli.recipe.Recipe;
import com.flauschcode.broccoli.recipe.images.RecipeImageService;

Expand All @@ -16,7 +18,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

class ImportableRecipeBuilder {

Expand All @@ -27,7 +28,7 @@ class ImportableRecipeBuilder {
private static final String ITEM_LIST_ELEMENT = "itemListElement";

private static final String NAME = "name";
private static final String RECIPE_DESCRIPTION = "description";
private static final String DESCRIPTION = "description";
private static final String RECIPE_INGREDIENT = "recipeIngredient";
private static final String RECIPE_INSTRUCTIONS = "recipeInstructions";
private static final String HOW_TO_TEXT = "text";
Expand All @@ -36,13 +37,21 @@ class ImportableRecipeBuilder {
private static final String COOK_TIME = "cookTime";
private static final String RECIPE_IMAGE = "image";
private static final String RECIPE_URL = "url";

private static final String NUTRITION = "nutrition";
private static final String SERVING_SIZE = "servingSize";
private static final String CALORIES = "calories";
private static final String FAT_CONTENT = "fatContent";
private static final String CARBOHYDRATE_CONTENT = "carbohydrateContent";
private static final String PROTEIN_CONTENT = "proteinContent";

private JSONObject recipeJson;
private Recipe recipe = new Recipe();
private final Recipe recipe = new Recipe();

private RecipeImageService recipeImageService;
private final Application application;
private final RecipeImageService recipeImageService;

public ImportableRecipeBuilder(RecipeImageService recipeImageService) {
public ImportableRecipeBuilder(Application application, RecipeImageService recipeImageService) {
this.application = application;
this.recipeImageService = recipeImageService;
}

Expand All @@ -67,6 +76,7 @@ Optional<Recipe> build() {
contributePreparationTime();
contributeIngredients();
contributeDirections();
contributeNutritionalInformation();
contributeImage();

return Optional.of(recipe);
Expand All @@ -77,7 +87,7 @@ private void contributeTitle() {
}

private void contributeDescription() {
recipe.setDescription(recipeJson.optString(RECIPE_DESCRIPTION));
recipe.setDescription(recipeJson.optString(DESCRIPTION));
}

private void contributeServings() {
Expand Down Expand Up @@ -115,7 +125,7 @@ private void contributeIngredients() {
for (int i = 0; i < ingredientArray.length(); i++) {
list.add(ingredientArray.optString(i));
}
recipe.setIngredients(list.stream().collect(Collectors.joining("\n")));
recipe.setIngredients(String.join("\n", list));
}
}

Expand All @@ -135,7 +145,29 @@ private void contributeDirections() {
}

}
recipe.setDirections(directions.stream().collect(Collectors.joining("\n")));
recipe.setDirections(String.join("\n", directions));
}
}

private void contributeNutritionalInformation() {
contributeNutritionalInformationFor(SERVING_SIZE, R.string.serving);
contributeNutritionalInformationFor(CALORIES, R.string.calories);
contributeNutritionalInformationFor(FAT_CONTENT, R.string.fat);
contributeNutritionalInformationFor(CARBOHYDRATE_CONTENT, R.string.carbohydrates);
contributeNutritionalInformationFor(PROTEIN_CONTENT, R.string.protein);
}

private void contributeNutritionalInformationFor(String jsonKey, int resourceKey) {
JSONObject nutritionalValuesObject = recipeJson.optJSONObject(NUTRITION);
if (nutritionalValuesObject == null) {
return;
}

String nutritionalValue = nutritionalValuesObject.optString(jsonKey);
if (!nutritionalValue.isEmpty()) {
StringBuilder stringBuilder = new StringBuilder(recipe.getNutritionalValues());
stringBuilder.append(application.getString(resourceKey).toUpperCase()).append(" ").append(nutritionalValue).append("\n"); recipe.setNutritionalValues(recipe.getNutritionalValues());
recipe.setNutritionalValues(recipe.getNutritionalValues());
}
}

Expand All @@ -148,7 +180,7 @@ private String contributeSection(JSONObject instructionObject) {
steps.add(contributeStep(sectionsArray, i));
}
}
return steps.stream().collect(Collectors.joining(" "));
return String.join(" ", steps);
}

private String contributeStep(JSONArray jsonArray, int position) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.flauschcode.broccoli.recipe.importing;

import android.app.Application;
import android.util.Log;

import com.flauschcode.broccoli.recipe.Recipe;
Expand All @@ -22,22 +23,26 @@

public class RecipeImportService {

private static final String USER_AGENT = "Mozilla/5.0";

private static final String FIELD_GRAPH = "@graph";
private static final String FIELD_TYPE = "@type";
private static final String TYPE_RECIPE = "Recipe";

private RecipeImageService recipeImageService;
private final Application application;
private final RecipeImageService recipeImageService;

@Inject
public RecipeImportService(RecipeImageService recipeImageService) {
public RecipeImportService(Application application, RecipeImageService recipeImageService) {
this.application = application;
this.recipeImageService = recipeImageService;
}

public CompletableFuture<Optional<Recipe>> importFrom(String url) {
return CompletableFuture.supplyAsync(() -> {
Document document;
try {
document = Jsoup.connect(url).get();
document = Jsoup.connect(url).userAgent(USER_AGENT).get();
} catch (IOException e) {
throw new CompletionException(e);
}
Expand All @@ -46,7 +51,7 @@ public CompletableFuture<Optional<Recipe>> importFrom(String url) {

Optional<JSONObject> recipeJsonLd = findRecipeIn(jsonLds);
if (recipeJsonLd.isPresent()) {
return new ImportableRecipeBuilder(recipeImageService).withRecipeJsonLd(recipeJsonLd.get()).from(url).build();
return new ImportableRecipeBuilder(application, recipeImageService).withRecipeJsonLd(recipeJsonLd.get()).from(url).build();
}

return Optional.empty();
Expand Down Expand Up @@ -106,11 +111,11 @@ private boolean theTopLevelStructureIsAnArray(Object json) {
}

private boolean thereIsAGraphObject(Object json) {
return json instanceof JSONObject && ((JSONObject) json).has(FIELD_GRAPH);
return json instanceof JSONObject jsonObject && jsonObject.has(FIELD_GRAPH);
}

private boolean theRecipeIsTheTopLevelObject(Object json) {
return json instanceof JSONObject && isRecipe((JSONObject) json);
return json instanceof JSONObject jsonObject && isRecipe((jsonObject));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
@Singleton
public class ShareableRecipeBuilder {

private Application application;
private RecipeImageService recipeImageService;
private final Application application;
private final RecipeImageService recipeImageService;

@Inject
ShareableRecipeBuilder(Application application, RecipeImageService recipeImageService) {
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<string name="directions">Anleitung</string>
<string name="nutritional_values">Nährwerte</string>
<string name="notes">Notizen</string>
<string name="protein">Eiweiß</string>
<string name="recipe_photo_accessibility">Rezept-Foto</string>
<string name="change_photo">Foto ändern</string>
<string name="remove_photo">Foto entfernen</string>
Expand Down Expand Up @@ -542,4 +543,8 @@
<string name="chinese_yam_terms">Chinesische Yamswurzeln, Yamswurzeln</string>
<string name="yuzu">Yuzu</string>
<string name="yuzu_terms">Yuzu</string>
<string name="serving">Portion</string>
<string name="calories">Kalorien</string>
<string name="fat">Fett</string>
<string name="carbohydrates">Kohlenhydrate</string>
</resources>
7 changes: 6 additions & 1 deletion app/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
<string name="preparation_time">Tiempo</string>
<string name="ingredients">Ingredientes</string>
<string name="directions">Instrucciones</string>
<string name="nutritional_values">Valores nutricionales</string>
<string name="nutritional_values">Nutrición</string>
<string name="notes">Notas</string>
<string name="protein">Proteína</string>
<string name="recipe_photo_accessibility">Foto de la receta</string>
<string name="change_photo">Cambiar foto</string>
<string name="remove_photo">Eliminar la foto</string>
Expand Down Expand Up @@ -246,4 +247,8 @@
<string name="champignons_terms">champiñones</string>
<string name="norwegian_bokmal">Noruego bokmål</string>
<string name="russian">Ruso</string>
<string name="serving">Porción</string>
<string name="calories">Calorías</string>
<string name="fat">Grasa</string>
<string name="carbohydrates">Carbohidratos</string>
</resources>
8 changes: 7 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,15 @@
<string name="preparation_time">Time</string>
<string name="ingredients">Ingredients</string>
<string name="directions">Directions</string>
<string name="nutritional_values">Nutritional values</string>
<string name="nutritional_values">Nutrition</string>
<string name="notes">Notes</string>

<string name="serving">Serving</string>
<string name="calories">Calories</string>
<string name="fat">Fat</string>
<string name="carbohydrates">Carbohydrates</string>
<string name="protein">Protein</string>

<string name="recipe_photo_accessibility">Recipe photo</string>
<string name="change_photo">Change photo</string>
<string name="remove_photo">Remove photo</string>
Expand Down

0 comments on commit c8e8145

Please sign in to comment.