Skip to content

Commit

Permalink
Merge pull request #95 from folded-ear/include-photo-on-copy
Browse files Browse the repository at this point in the history
Include photo on copy
  • Loading branch information
barneyb authored Aug 15, 2024
2 parents cb6b95f + b90a8f8 commit 505992d
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 13 deletions.
13 changes: 10 additions & 3 deletions src/main/java/com/brennaswitzer/cookbook/domain/Photo.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ public class Photo {

@Embedded
private S3File file;
public void clearFile() {
file = null;
}
public boolean hasFile() {
return file != null;
}
Expand Down Expand Up @@ -50,6 +47,10 @@ public String getObjectKey() {
return file.getObjectKey();
}

public String getFilename() {
return file.getFilename();
}

public String getContentType() {
return file.getContentType();
}
Expand All @@ -58,4 +59,10 @@ public Long getSize() {
return file.getSize();
}

public void clear() {
file = null;
focusLeft = null;
focusTop = null;
}

}
5 changes: 2 additions & 3 deletions src/main/java/com/brennaswitzer/cookbook/domain/Recipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OrderBy;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import lombok.Getter;
import lombok.Setter;
Expand Down Expand Up @@ -82,7 +81,7 @@ public void setPhoto(S3File file) {
}
public void clearPhoto() {
if (hasPhoto()) {
photo.clearFile();
photo.clear();
}
}
public boolean hasPhoto() {
Expand Down Expand Up @@ -129,7 +128,7 @@ public void addRawIngredient(String raw) {
ingredients.add(new IngredientRef(raw));
}

@PrePersist
@Override
protected void onPrePersist() {
super.onPrePersist();
ensureRefOrder();
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/brennaswitzer/cookbook/domain/S3File.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ private static String lastSegment(String string, char delim) {

private Long size; // needs to be nullable for historical data

public String getFilename() {
return lastSegment(objectKey, '/');
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public Recipe createRecipe(IngredientInfo info, Part photo, boolean cookThis) {
return recipe;
}

public Recipe createRecipeFrom(Long sourceRecipeId, IngredientInfo info, Part photo) {
Recipe recipe = info.asRecipe(entityManager);
recipe = recipeService.createNewRecipeFrom(sourceRecipeId, recipe, Upload.of(photo));
labelService.updateLabels(recipe, info.getLabels());
return recipe;
}

public Recipe updateRecipe(Long id, IngredientInfo info, Part photo) {
info.setId(id);
Recipe recipe = info.asRecipe(entityManager);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ public String store(Upload upload, String filename) {
return "images/pork_chops.jpg";
}

@Override
public String copy(String source, String dest) {
Assert.notNull(source, "source is required.");
Assert.notNull(dest, "dest is required.");
return "images/pork_chops.jpg";
}

@Override
public String load(String filename) {
Assert.notNull(filename, "Filename is required");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.brennaswitzer.cookbook.services;

import com.brennaswitzer.cookbook.domain.Photo;
import com.brennaswitzer.cookbook.domain.Recipe;
import com.brennaswitzer.cookbook.domain.S3File;
import com.brennaswitzer.cookbook.domain.Upload;
Expand Down Expand Up @@ -47,6 +48,18 @@ public Recipe createNewRecipe(Recipe recipe, Upload photo) {
return recipe;
}

public Recipe createNewRecipeFrom(Long sourceRecipeId, Recipe recipe, Upload photo) {
var source = recipeRepository.getReferenceById(sourceRecipeId);
recipe.setOwner(principalAccess.getUser());
recipe = recipeRepository.save(recipe);
if (photo != null) {
setPhotoInternal(recipe, photo);
} else if (source.hasPhoto()) {
copyPhoto(source, recipe);
}
return recipe;
}

public Recipe updateRecipe(Recipe recipe) {
return this.updateRecipe(recipe, null);
}
Expand Down Expand Up @@ -92,12 +105,31 @@ private void setPhotoInternal(Recipe recipe, Upload photo) {
} else {
name = S3File.sanitizeFilename(name);
}
String objectKey = "recipe/" + recipe.getId() + "/" + name;
recipe.setPhoto(new S3File(
storageService.store(photo, objectKey),
storageService.store(photo,
buildObjectKey(recipe, name)),
photo.getContentType(),
photo.getSize()
));
}

private void copyPhoto(Recipe source, Recipe dest) {
removePhotoInternal(dest);
if (!source.hasPhoto()) return; // silly caller
Photo photo = source.getPhoto();
dest.setPhoto(new S3File(
storageService.copy(photo.getObjectKey(),
buildObjectKey(dest, photo.getFilename())),
photo.getContentType(),
photo.getSize()
));
if (photo.hasFocus()) {
dest.getPhoto().setFocusArray(photo.getFocusArray());
}
}

private String buildObjectKey(Recipe recipe, String name) {
return "recipe/" + recipe.getId() + "/" + name;
}

private void removePhotoInternal(Recipe recipe) {
Expand All @@ -106,10 +138,6 @@ private void removePhotoInternal(Recipe recipe) {
recipe.clearPhoto();
}

public void sendToPlan(Long recipeId, Long planId) {
sendToPlan(recipeId, planId, 1d);
}

@SuppressWarnings("OptionalGetWithoutIsPresent")
public void sendToPlan(Long recipeId, Long planId, Double scale) {
planService.addRecipe(planId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ public String store(Upload upload, String objectKey) {
return objectKey;
}

@Override
public String copy(String source, String dest) {
Assert.notNull(source, "source is required.");
Assert.notNull(dest, "dest is required.");
client.copyObject(bucketName, source, bucketName, dest);
return dest;
}

@Override
public String load(String objectKey) {
Assert.notNull(objectKey, "objectKey is required");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@
public interface StorageService {

/**
* I take a Upload object and a string filename/key and write to storage
* I take an Upload object and a string filename/key and write to storage
* @param filename String filename for storage
* @return reference to the stored file
*/
String store(Upload upload, String filename);

/**
* I take two string filename/keys and copy the content of the first to the
* second. A complete copy is made, no backreferences are created.
*
* @param source String filename to copy from
* @param dest String filename to copy to
* @return reference to the stored (destination) file
*/
String copy(String source, String dest);

/**
* I return a fully-qualified URL for the passed file reference.
* @param ref A reference to a stored file.
Expand Down
13 changes: 13 additions & 0 deletions src/main/resources/graphqls/library.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,22 @@ extend type Mutation {
}

type LibraryMutation {
"""Create a new recipe in your library, from the passed info.
"""
createRecipe(info: IngredientInfo!, photo: Upload, cookThis: Boolean): Recipe!
"""Create a new recipe in your library, from the passed info, which is based
on the passed source recipe id.
"""
createRecipeFrom(sourceRecipeId: ID!, info: IngredientInfo!, photo: Upload): Recipe!
"""Update a recipe in your library, from the passed info.
"""
updateRecipe(id: ID!, info: IngredientInfo!, photo: Upload): Recipe!
"""Set the photo for a recipe in your library, without changing any other
info about the recipe. A photo may be set during create and/or update.
"""
setRecipePhoto(id: ID!, photo: Upload!): Recipe!
"""Delete a recipe from your library.
"""
deleteRecipe(id: ID!): Deletion!
history(recipeId: ID!): RecipeHistoryMutation
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,24 @@ void createRecipe_cookThis() {
verify(labelService).updateLabels(same(recipe), same(labels));
}

@Test
void createRecipeFrom() {
var recipe = mock(Recipe.class);
List<String> labels = new ArrayList<>();
var info = mock(IngredientInfo.class);
when(info.getLabels()).thenReturn(labels);
when(info.asRecipe(any())).thenReturn(recipe);
when(recipeService.createNewRecipeFrom(any(), any(), any()))
.thenAnswer(iom -> iom.getArgument(1));

var result = mutation.createRecipeFrom(123L, info, null);

assertSame(recipe, result);
verify(info).asRecipe(entityManager);
verify(recipeService).createNewRecipeFrom(eq(123L), same(recipe), isNull());
verify(labelService).updateLabels(same(recipe), same(labels));
}

@Test
void updateRecipe() {
var recipe = mock(Recipe.class);
Expand Down

0 comments on commit 505992d

Please sign in to comment.