From 03e195ed53f1f308ddbdee64285fa39d2391fb28 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Mon, 1 Aug 2022 11:47:33 +0100 Subject: [PATCH 1/3] 1361 Add image deletion --- .../elimu/dao/ImageContributionEventDao.java | 6 +- src/main/java/ai/elimu/dao/StoryBookDao.java | 3 + .../dao/jpa/ImageContributionEventDaoJpa.java | 20 ++-- .../ai/elimu/dao/jpa/StoryBookDaoJpa.java | 13 ++ .../multimedia/image/ImageComponent.java | 83 +++++++++++++ .../image/ImageDeleteController.java | 38 ++++-- .../multimedia/image/ImageEditController.java | 66 +---------- .../webapp/WEB-INF/i18n/errors_en.properties | 1 + .../jsp/content/multimedia/image/edit.jsp | 8 +- src/test/java/ai/elimu/dao/BaseDaoTest.java | 24 +--- .../dao/ImageContributionEventDaoTest.java | 112 ++++++++++++++++++ src/test/java/ai/elimu/dao/ImageDaoTest.java | 18 ++- .../java/ai/elimu/dao/StoryBookDaoTest.java | 61 ++++++++++ .../java/ai/elimu/utilTest/ImageUtil.java | 26 ++++ .../image/ImageDeleteControllerTest.java | 78 ++++++++++++ 15 files changed, 454 insertions(+), 103 deletions(-) create mode 100644 src/main/java/ai/elimu/web/content/multimedia/image/ImageComponent.java create mode 100644 src/test/java/ai/elimu/dao/ImageContributionEventDaoTest.java create mode 100644 src/test/java/ai/elimu/dao/StoryBookDaoTest.java create mode 100644 src/test/java/ai/elimu/utilTest/ImageUtil.java create mode 100644 src/test/java/ai/elimu/web/content/multimedia/image/ImageDeleteControllerTest.java diff --git a/src/main/java/ai/elimu/dao/ImageContributionEventDao.java b/src/main/java/ai/elimu/dao/ImageContributionEventDao.java index abe403d44..ae8787d98 100644 --- a/src/main/java/ai/elimu/dao/ImageContributionEventDao.java +++ b/src/main/java/ai/elimu/dao/ImageContributionEventDao.java @@ -11,8 +11,8 @@ public interface ImageContributionEventDao extends GenericDao readAll(Image image) throws DataAccessException; List readAll(Contributor contributor) throws DataAccessException; - - List readMostRecent(int maxResults) throws DataAccessException; - + Long readCount(Contributor contributor) throws DataAccessException; + + void deleteAllEventsForImage(Image image); } diff --git a/src/main/java/ai/elimu/dao/StoryBookDao.java b/src/main/java/ai/elimu/dao/StoryBookDao.java index 53b00aa57..7ffdac960 100644 --- a/src/main/java/ai/elimu/dao/StoryBookDao.java +++ b/src/main/java/ai/elimu/dao/StoryBookDao.java @@ -3,6 +3,7 @@ import java.util.List; import ai.elimu.model.content.StoryBook; +import ai.elimu.model.content.multimedia.Image; import ai.elimu.model.v2.enums.ReadingLevel; import org.springframework.dao.DataAccessException; @@ -16,4 +17,6 @@ public interface StoryBookDao extends GenericDao { List readAllOrdered(ReadingLevel readingLevel) throws DataAccessException; List readAllUnleveled() throws DataAccessException; + + List readAllWithImage(Image image) throws DataAccessException; } diff --git a/src/main/java/ai/elimu/dao/jpa/ImageContributionEventDaoJpa.java b/src/main/java/ai/elimu/dao/jpa/ImageContributionEventDaoJpa.java index a079e09c2..3e4dd4981 100644 --- a/src/main/java/ai/elimu/dao/jpa/ImageContributionEventDaoJpa.java +++ b/src/main/java/ai/elimu/dao/jpa/ImageContributionEventDaoJpa.java @@ -31,16 +31,6 @@ public List readAll(Contributor contributor) throws Data .getResultList(); } - @Override - public List readMostRecent(int maxResults) throws DataAccessException { - return em.createQuery( - "SELECT ice " + - "FROM ImageContributionEvent ice " + - "ORDER BY ice.time DESC") - .setMaxResults(maxResults) - .getResultList(); - } - @Override public Long readCount(Contributor contributor) throws DataAccessException { return (Long) em.createQuery("SELECT COUNT(ice) " + @@ -49,4 +39,14 @@ public Long readCount(Contributor contributor) throws DataAccessException { .setParameter("contributor", contributor) .getSingleResult(); } + + @Override + public void deleteAllEventsForImage(Image image) { + em.createQuery("DELETE " + + "FROM ImageContributionEvent ice " + + "WHERE ice.image = :image") + .setParameter("image", image) + .executeUpdate(); + } + } diff --git a/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java b/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java index 96fd8d67b..0d43c7628 100644 --- a/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java +++ b/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java @@ -4,6 +4,7 @@ import javax.persistence.NoResultException; import ai.elimu.dao.StoryBookDao; +import ai.elimu.model.content.multimedia.Image; import org.springframework.dao.DataAccessException; import ai.elimu.model.content.StoryBook; @@ -54,4 +55,16 @@ public List readAllUnleveled() throws DataAccessException { "ORDER BY book.title") .getResultList(); } + + @Override + public List readAllWithImage(Image image) throws DataAccessException { + return em.createQuery( + "SELECT book " + + "FROM StoryBook book " + + "WHERE book.coverImage.id = :image ") + .setParameter("image", image.getId()) + .getResultList(); + + } + } diff --git a/src/main/java/ai/elimu/web/content/multimedia/image/ImageComponent.java b/src/main/java/ai/elimu/web/content/multimedia/image/ImageComponent.java new file mode 100644 index 000000000..216cbe2b8 --- /dev/null +++ b/src/main/java/ai/elimu/web/content/multimedia/image/ImageComponent.java @@ -0,0 +1,83 @@ +package ai.elimu.web.content.multimedia.image; + +import ai.elimu.dao.*; +import ai.elimu.model.content.Emoji; +import ai.elimu.model.content.Word; +import ai.elimu.model.content.multimedia.Audio; +import ai.elimu.model.content.multimedia.Image; +import ai.elimu.model.enums.ContentLicense; +import ai.elimu.model.v2.enums.content.LiteracySkill; +import ai.elimu.model.v2.enums.content.NumeracySkill; +import org.apache.commons.lang.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.ui.Model; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ImageComponent { + + private final Logger logger = LogManager.getLogger(); + + @Autowired + private LetterDao letterDao; + + @Autowired + private NumberDao numberDao; + + @Autowired + private WordDao wordDao; + + @Autowired + private EmojiDao emojiDao; + + @Autowired + private AudioDao audioDao; + + @Autowired + private ImageContributionEventDao imageContributionEventDao; + + public void setImageModel(Model model, Image image) { + model.addAttribute("image", image); + model.addAttribute("contentLicenses", ContentLicense.values()); + model.addAttribute("literacySkills", LiteracySkill.values()); + model.addAttribute("numeracySkills", NumeracySkill.values()); + + model.addAttribute("timeStart", System.currentTimeMillis()); + model.addAttribute("imageContributionEvents", imageContributionEventDao.readAll(image)); + + model.addAttribute("letters", letterDao.readAllOrdered()); + model.addAttribute("numbers", numberDao.readAllOrdered()); + model.addAttribute("words", wordDao.readAllOrdered()); + model.addAttribute("emojisByWordId", getEmojisByWordId()); + + Audio audio = audioDao.readByTranscription(image.getTitle()); + model.addAttribute("audio", audio); + } + + private Map getEmojisByWordId() { + logger.info("getEmojisByWordId"); + + Map emojisByWordId = new HashMap<>(); + + for (Word word : wordDao.readAll()) { + String emojiGlyphs = ""; + + List emojis = emojiDao.readAllLabeled(word); + for (Emoji emoji : emojis) { + emojiGlyphs += emoji.getGlyph(); + } + + if (StringUtils.isNotBlank(emojiGlyphs)) { + emojisByWordId.put(word.getId(), emojiGlyphs); + } + } + + return emojisByWordId; + } +} diff --git a/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java b/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java index d486504c5..23b65b282 100644 --- a/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java +++ b/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java @@ -1,7 +1,8 @@ package ai.elimu.web.content.multimedia.image; +import ai.elimu.dao.*; +import ai.elimu.model.content.multimedia.Image; import org.apache.logging.log4j.Logger; -import ai.elimu.dao.ImageDao; import org.apache.logging.log4j.LogManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @@ -10,6 +11,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import java.util.HashSet; + @Controller @RequestMapping("/content/multimedia/image/delete") public class ImageDeleteController { @@ -19,20 +22,39 @@ public class ImageDeleteController { @Autowired private ImageDao imageDao; + @Autowired + private StoryBookDao storyBookDao; + + @Autowired + private ImageComponent imageComponent; + + @Autowired + private ImageContributionEventDao imageContributionEventDao; + @RequestMapping(value = "/{id}", method = RequestMethod.GET) public String handleRequest(Model model, @PathVariable Long id) { logger.info("handleRequest"); // Before deleting, check if the image is used in any StoryBooks - // TODO - + Image image = imageDao.read(id); + if (storyBookDao.readAllWithImage(image).size() > 0) { + imageComponent.setImageModel(model, image); + model.addAttribute("errorCode", "StoryBookContainImage"); + + return "content/multimedia/image/edit"; + } + // Before deleting, remove any labels - // TODO - + image.setLetters(new HashSet<>()); + image.setWords(new HashSet<>()); + image.setNumbers(new HashSet<>()); + imageDao.update(image); + + // Delete all contribution event connected with image + imageContributionEventDao.deleteAllEventsForImage(image); + // Delete the image from the database - // TODO -// Image image = imageDao.read(id); -// imageDao.delete(image); + imageDao.delete(image); // Store contribution event // TODO diff --git a/src/main/java/ai/elimu/web/content/multimedia/image/ImageEditController.java b/src/main/java/ai/elimu/web/content/multimedia/image/ImageEditController.java index c84222fc2..bdb865c6c 100644 --- a/src/main/java/ai/elimu/web/content/multimedia/image/ImageEditController.java +++ b/src/main/java/ai/elimu/web/content/multimedia/image/ImageEditController.java @@ -16,26 +16,18 @@ import ai.elimu.dao.LetterDao; import ai.elimu.dao.NumberDao; import ai.elimu.dao.WordDao; -import ai.elimu.model.content.Emoji; import ai.elimu.model.content.Letter; import ai.elimu.model.content.Number; import ai.elimu.model.content.Word; -import ai.elimu.model.content.multimedia.Audio; import ai.elimu.model.content.multimedia.Image; import ai.elimu.model.contributor.Contributor; import ai.elimu.model.contributor.ImageContributionEvent; -import ai.elimu.model.enums.ContentLicense; import ai.elimu.model.enums.Platform; import ai.elimu.model.v2.enums.content.ImageFormat; -import ai.elimu.model.v2.enums.content.LiteracySkill; -import ai.elimu.model.v2.enums.content.NumeracySkill; import ai.elimu.util.DiscordHelper; import ai.elimu.util.ImageHelper; import ai.elimu.web.context.EnvironmentContextLoaderListener; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import javax.servlet.http.HttpSession; import org.apache.logging.log4j.LogManager; import org.springframework.beans.factory.annotation.Autowired; @@ -79,6 +71,9 @@ public class ImageEditController { @Autowired private AudioDao audioDao; + @Autowired + ImageComponent imageComponent; + @RequestMapping(value = "/{id}", method = RequestMethod.GET) public String handleRequest( Model model, @@ -86,21 +81,7 @@ public String handleRequest( logger.info("handleRequest"); Image image = imageDao.read(id); - model.addAttribute("image", image); - model.addAttribute("contentLicenses", ContentLicense.values()); - model.addAttribute("literacySkills", LiteracySkill.values()); - model.addAttribute("numeracySkills", NumeracySkill.values()); - - model.addAttribute("timeStart", System.currentTimeMillis()); - model.addAttribute("imageContributionEvents", imageContributionEventDao.readAll(image)); - - model.addAttribute("letters", letterDao.readAllOrdered()); - model.addAttribute("numbers", numberDao.readAllOrdered()); - model.addAttribute("words", wordDao.readAllOrdered()); - model.addAttribute("emojisByWordId", getEmojisByWordId()); - - Audio audio = audioDao.readByTranscription(image.getTitle()); - model.addAttribute("audio", audio); + imageComponent.setImageModel(model, image); return "content/multimedia/image/edit"; } @@ -175,22 +156,7 @@ public String handleSubmit( } if (result.hasErrors()) { - model.addAttribute("image", image); - model.addAttribute("contentLicenses", ContentLicense.values()); - model.addAttribute("literacySkills", LiteracySkill.values()); - model.addAttribute("numeracySkills", NumeracySkill.values()); - - model.addAttribute("timeStart", System.currentTimeMillis()); - model.addAttribute("imageContributionEvents", imageContributionEventDao.readAll(image)); - - model.addAttribute("letters", letterDao.readAllOrdered()); - model.addAttribute("numbers", numberDao.readAllOrdered()); - model.addAttribute("words", wordDao.readAllOrdered()); - model.addAttribute("emojisByWordId", getEmojisByWordId()); - - Audio audio = audioDao.readByTranscription(image.getTitle()); - model.addAttribute("audio", audio); - + imageComponent.setImageModel(model, image); return "content/multimedia/image/edit"; } else { image.setTitle(image.getTitle().toLowerCase()); @@ -349,25 +315,5 @@ public String handleRemoveContentLabelRequest( return "success"; } - - private Map getEmojisByWordId() { - logger.info("getEmojisByWordId"); - - Map emojisByWordId = new HashMap<>(); - - for (Word word : wordDao.readAll()) { - String emojiGlyphs = ""; - - List emojis = emojiDao.readAllLabeled(word); - for (Emoji emoji : emojis) { - emojiGlyphs += emoji.getGlyph(); - } - - if (StringUtils.isNotBlank(emojiGlyphs)) { - emojisByWordId.put(word.getId(), emojiGlyphs); - } - } - - return emojisByWordId; - } + } diff --git a/src/main/webapp/WEB-INF/i18n/errors_en.properties b/src/main/webapp/WEB-INF/i18n/errors_en.properties index 63b76e5be..134ad095a 100644 --- a/src/main/webapp/WEB-INF/i18n/errors_en.properties +++ b/src/main/webapp/WEB-INF/i18n/errors_en.properties @@ -32,3 +32,4 @@ formatHint.Integer=Number (e.g. "5000") image.too.small=The image width must be at least 640px emoji.unicode.version=Only emojis up to Unicode version 9 WordSpace=Spaces are not allowed +StoryBookContainImage=Story book contain image \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/content/multimedia/image/edit.jsp b/src/main/webapp/WEB-INF/jsp/content/multimedia/image/edit.jsp index eed057316..e68f369d0 100644 --- a/src/main/webapp/WEB-INF/jsp/content/multimedia/image/edit.jsp +++ b/src/main/webapp/WEB-INF/jsp/content/multimedia/image/edit.jsp @@ -8,7 +8,13 @@
- + + +
+ +
+
+ diff --git a/src/test/java/ai/elimu/dao/BaseDaoTest.java b/src/test/java/ai/elimu/dao/BaseDaoTest.java index 56c4bef70..2dd15fd23 100644 --- a/src/test/java/ai/elimu/dao/BaseDaoTest.java +++ b/src/test/java/ai/elimu/dao/BaseDaoTest.java @@ -1,9 +1,9 @@ package ai.elimu.dao; -import ai.elimu.dao.ImageDao; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import ai.elimu.utilTest.ImageUtil; import org.junit.Test; import org.junit.runner.RunWith; import ai.elimu.model.content.multimedia.Image; @@ -23,21 +23,18 @@ public class BaseDaoTest { @Test public void testCreate() { - Image image1 = new Image(); - image1.setTitle("Title1"); + Image image1 = ImageUtil.getImage("Title1"); imageDao.create(image1); assertNotNull(image1.getId()); - Image image2 = new Image(); - image2.setTitle("Title1"); + Image image2 = ImageUtil.getImage("Title1"); imageDao.create(image2); assertNotNull(image2.getId()); } @Test public void testRead() { - Image image1 = new Image(); - image1.setTitle("Title1"); + Image image1 = ImageUtil.getImage("Title1"); imageDao.create(image1); assertNotNull(image1.getId()); assertNotNull(imageDao.read(image1.getId())); @@ -45,12 +42,12 @@ public void testRead() { @Test public void testReadAll() { - Image image1 = new Image(); + Image image1 = ImageUtil.getImage("Title1"); image1.setTitle("Title1"); imageDao.create(image1); assertNotNull(image1.getId()); - Image image2 = new Image(); + Image image2 = ImageUtil.getImage("Title1"); image2.setTitle("Title1"); imageDao.create(image2); assertNotNull(image2.getId()); @@ -58,13 +55,4 @@ public void testReadAll() { assertTrue(imageDao.readAll().size() >= 2); } - @Test - public void testUpdate() { - // TODO - } - - @Test - public void testDelete() { - // TODO - } } diff --git a/src/test/java/ai/elimu/dao/ImageContributionEventDaoTest.java b/src/test/java/ai/elimu/dao/ImageContributionEventDaoTest.java new file mode 100644 index 000000000..069bc7338 --- /dev/null +++ b/src/test/java/ai/elimu/dao/ImageContributionEventDaoTest.java @@ -0,0 +1,112 @@ +package ai.elimu.dao; + +import ai.elimu.model.content.multimedia.Image; +import ai.elimu.model.contributor.Contributor; +import ai.elimu.model.contributor.ImageContributionEvent; +import ai.elimu.model.enums.Platform; +import ai.elimu.utilTest.ImageUtil; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Calendar; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations={ + "file:src/main/webapp/WEB-INF/spring/applicationContext.xml", + "file:src/main/webapp/WEB-INF/spring/applicationContext-jpa.xml" +}) +public class ImageContributionEventDaoTest extends TestCase { + + @Autowired + private ImageContributionEventDao imageContributionEventDao; + + @Autowired + private ContributorDao contributorDao; + + @Autowired + private ImageDao imageDao; + + @Test + public void testReadCount() { + imageDao.create(ImageUtil.getImage("Test read count")); + Image image = imageDao.read("Test read count"); + contributorDao.create(getContributor("test@email.com")); + Contributor contributor = contributorDao.read("test@email.com"); + + assertEquals(0, (long) imageContributionEventDao.readCount(contributor)); + + imageContributionEventDao.create(getImageContributionEvent(image, contributor)); + imageContributionEventDao.create(getImageContributionEvent(image, contributor)); + + assertEquals(2, (long) imageContributionEventDao.readCount(contributor)); + } + + @Test + public void testReadAllForImage() { + imageDao.create(ImageUtil.getImage("Test read all for image")); + Image image = imageDao.read("Test read all for image"); + + assertEquals(0, imageContributionEventDao.readAll(image).size()); + + imageContributionEventDao.create(getImageContributionEvent(image)); + imageContributionEventDao.create(getImageContributionEvent(image)); + + assertEquals(2, imageContributionEventDao.readAll(image).size()); + } + + @Test + public void testReadAllForContributor() { + imageDao.create(ImageUtil.getImage("Test read all for contributor")); + Image image = imageDao.read("Test read all for contributor"); + contributorDao.create(getContributor("test1@email.com")); + Contributor contributor = contributorDao.read("test1@email.com"); + + assertEquals(0, imageContributionEventDao.readAll(contributor).size()); + + imageContributionEventDao.create(getImageContributionEvent(image, contributor)); + imageContributionEventDao.create(getImageContributionEvent(image, contributor)); + + assertEquals(2, imageContributionEventDao.readAll(contributor).size()); + } + + @Test + public void testDeleteAllEventsForImage() { + imageDao.create(ImageUtil.getImage("Image for event")); + Image image = imageDao.read("Image for event"); + imageContributionEventDao.create(getImageContributionEvent(image)); + + assertTrue(imageContributionEventDao.readAll(image).size() > 0); + + imageContributionEventDao.deleteAllEventsForImage(image); + + assertEquals(0, imageContributionEventDao.readAll(image).size()); + } + + private ImageContributionEvent getImageContributionEvent(Image image) { + ImageContributionEvent imageContributionEvent = new ImageContributionEvent(); + imageContributionEvent.setImage(image); + imageContributionEvent.setRevisionNumber(1); + imageContributionEvent.setTime(Calendar.getInstance()); + imageContributionEvent.setTimeSpentMs(1L); + imageContributionEvent.setPlatform(Platform.WEBAPP); + return imageContributionEvent; + } + + private ImageContributionEvent getImageContributionEvent(Image image, Contributor contributor) { + ImageContributionEvent imageContributionEvent = getImageContributionEvent(image); + imageContributionEvent.setContributor(contributor); + return imageContributionEvent; + } + + private Contributor getContributor(String email) { + Contributor contributor = new Contributor(); + contributor.setEmail(email); + contributor.setRegistrationTime(Calendar.getInstance()); + return contributor; + } + +} \ No newline at end of file diff --git a/src/test/java/ai/elimu/dao/ImageDaoTest.java b/src/test/java/ai/elimu/dao/ImageDaoTest.java index 026434f2c..a6eb6bc2e 100644 --- a/src/test/java/ai/elimu/dao/ImageDaoTest.java +++ b/src/test/java/ai/elimu/dao/ImageDaoTest.java @@ -3,6 +3,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; + +import ai.elimu.utilTest.ImageUtil; import org.apache.logging.log4j.Logger; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; @@ -47,9 +49,7 @@ public void testReadAllLabeled() { Set words = new HashSet<>(); words.add(wordCat); - Image image = new Image(); - image.setTitle("image"); - image.setWords(words); + Image image = ImageUtil.getImage("image", words); imageDao.create(image); images = imageDao.readAllLabeled(wordDog); @@ -67,4 +67,16 @@ public void testReadAllLabeled() { assertThat(images.size(), is(1)); assertThat(images.get(0).getWords().size(), is(2)); } + + @Test + public void testDeleteImage() { + imageDao.create(ImageUtil.getImage("Image to delete")); + Image image = imageDao.read("Image to delete"); + + assertNotNull(image); + + imageDao.delete(image); + + assertNull(imageDao.read("Image to delete")); + } } diff --git a/src/test/java/ai/elimu/dao/StoryBookDaoTest.java b/src/test/java/ai/elimu/dao/StoryBookDaoTest.java new file mode 100644 index 000000000..c873850c2 --- /dev/null +++ b/src/test/java/ai/elimu/dao/StoryBookDaoTest.java @@ -0,0 +1,61 @@ +package ai.elimu.dao; + +import ai.elimu.model.content.StoryBook; +import ai.elimu.model.content.multimedia.Image; +import ai.elimu.model.v2.enums.content.ContentStatus; +import ai.elimu.utilTest.ImageUtil; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations={ + "file:src/main/webapp/WEB-INF/spring/applicationContext.xml", + "file:src/main/webapp/WEB-INF/spring/applicationContext-jpa.xml" +}) +public class StoryBookDaoTest extends TestCase { + + @Autowired + private StoryBookDao storyBookDao; + + @Autowired + ImageDao imageDao; + + @Test + public void testReadByTitle() { + assertNull(storyBookDao.readByTitle("test read by title")); + + storyBookDao.create(getStoryBook("test read by title")); + assertNotNull(storyBookDao.readByTitle("test read by title")); + } + + @Test + public void testReadAllWithImage() { + imageDao.create(ImageUtil.getImage("test read all with image")); + Image image = imageDao.read("test read all with image"); + + assertEquals(0, storyBookDao.readAllWithImage(image).size()); + + storyBookDao.create(getStoryBook("test read all with image", image)); + + assertEquals(1, storyBookDao.readAllWithImage(image).size()); + } + + private StoryBook getStoryBook(String title) { + StoryBook storyBook = new StoryBook(); + storyBook.setTitle(title); + storyBook.setRevisionNumber(1); + storyBook.setContentStatus(ContentStatus.ACTIVE); + return storyBook; + } + + private StoryBook getStoryBook(String title, Image image) { + StoryBook storyBook = getStoryBook(title); + storyBook.setCoverImage(image); + return storyBook; + } + +} \ No newline at end of file diff --git a/src/test/java/ai/elimu/utilTest/ImageUtil.java b/src/test/java/ai/elimu/utilTest/ImageUtil.java new file mode 100644 index 000000000..26d31aa66 --- /dev/null +++ b/src/test/java/ai/elimu/utilTest/ImageUtil.java @@ -0,0 +1,26 @@ +package ai.elimu.utilTest; + +import ai.elimu.model.content.Word; +import ai.elimu.model.content.multimedia.Image; +import ai.elimu.model.v2.enums.content.ImageFormat; + +import java.util.Set; + +public class ImageUtil { + + public static Image getImage(String title) { + Image image = new Image(); + image.setImageFormat(ImageFormat.GIF); + image.setTitle(title); + image.setBytes(new byte[1]); + image.setContentType("contentType"); + return image; + } + + public static Image getImage(String title, Set words) { + Image image = getImage(title); + image.setWords(words); + return image; + } + +} diff --git a/src/test/java/ai/elimu/web/content/multimedia/image/ImageDeleteControllerTest.java b/src/test/java/ai/elimu/web/content/multimedia/image/ImageDeleteControllerTest.java new file mode 100644 index 000000000..f105dd58c --- /dev/null +++ b/src/test/java/ai/elimu/web/content/multimedia/image/ImageDeleteControllerTest.java @@ -0,0 +1,78 @@ +package ai.elimu.web.content.multimedia.image; + +import ai.elimu.dao.ImageDao; +import ai.elimu.dao.StoryBookDao; +import ai.elimu.model.content.StoryBook; +import ai.elimu.model.content.multimedia.Image; +import ai.elimu.utilTest.ImageUtil; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.RequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations={ + "file:src/main/webapp/WEB-INF/spring/applicationContext.xml", + "file:src/main/webapp/WEB-INF/spring/applicationContext-jpa.xml" +}) +public class ImageDeleteControllerTest extends TestCase { + + @Autowired + ImageDeleteController imageDeleteController; + + @Autowired + ImageDao imageDao; + + @Autowired + StoryBookDao storyBookDao; + + private MockMvc mockMvc; + + @Before + public void setup() { + assertNotNull(imageDeleteController); + mockMvc = MockMvcBuilders.standaloneSetup(imageDeleteController).build(); + assertNotNull(mockMvc); + } + + @Test + public void testStoryBookContainImageError() throws Exception { + imageDao.create(ImageUtil.getImage("Title")); + Image image = imageDao.read("Title"); + + storyBookDao.create(getStoryBook(image)); + + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/content/multimedia/image/delete/" + image.getId()) + .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE); + assertEquals("StoryBookContainImage", mockMvc.perform(requestBuilder).andReturn().getModelAndView().getModel().get("errorCode")); + } + + @Test + public void testDeleteImage() throws Exception { + imageDao.create(ImageUtil.getImage("TitleRemove")); + Image image = imageDao.read("TitleRemove"); + + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/content/multimedia/image/delete/" + image.getId()) + .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE); + assertNull(mockMvc.perform(requestBuilder).andReturn().getModelAndView().getModel().get("errorCode")); + assertNull(imageDao.read("TitleRemove")); + } + + private StoryBook getStoryBook(Image image) { + StoryBook storyBook = new StoryBook(); + storyBook.setTitle("Story Book"); + storyBook.setCoverImage(image); + return storyBook; + } + +} \ No newline at end of file From 94d2ca238cc94cef8dd2a73eb9114e67805ce18e Mon Sep 17 00:00:00 2001 From: Tomasz Date: Thu, 11 Aug 2022 18:35:49 +0100 Subject: [PATCH 2/3] 1361 Add image deletion --- src/main/java/ai/elimu/dao/StoryBookChapterDao.java | 4 ++++ .../ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java | 13 +++++++++++++ .../multimedia/image/ImageDeleteController.java | 5 ++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/ai/elimu/dao/StoryBookChapterDao.java b/src/main/java/ai/elimu/dao/StoryBookChapterDao.java index def6ea6c2..b2a024e7a 100644 --- a/src/main/java/ai/elimu/dao/StoryBookChapterDao.java +++ b/src/main/java/ai/elimu/dao/StoryBookChapterDao.java @@ -4,9 +4,13 @@ import ai.elimu.model.content.StoryBook; import ai.elimu.model.content.StoryBookChapter; +import ai.elimu.model.content.multimedia.Image; import org.springframework.dao.DataAccessException; public interface StoryBookChapterDao extends GenericDao { List readAll(StoryBook storyBook) throws DataAccessException; + + List readAllWithImage(Image image) throws DataAccessException; + } diff --git a/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java b/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java index ac4f71af5..da9bbabb4 100644 --- a/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java +++ b/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java @@ -3,6 +3,7 @@ import ai.elimu.dao.StoryBookChapterDao; import java.util.List; +import ai.elimu.model.content.multimedia.Image; import org.springframework.dao.DataAccessException; import ai.elimu.model.content.StoryBook; @@ -20,4 +21,16 @@ public List readAll(StoryBook storyBook) throws DataAccessExce .setParameter("storyBook", storyBook) .getResultList(); } + + @Override + public List readAllWithImage(Image image) throws DataAccessException { + return em.createQuery( + "SELECT ch " + + "FROM StoryBookChapter ch " + + "WHERE ch.image.id = :image ") + .setParameter("image", image.getId()) + .getResultList(); + + } + } diff --git a/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java b/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java index 23b65b282..9d3a5d902 100644 --- a/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java +++ b/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java @@ -31,13 +31,16 @@ public class ImageDeleteController { @Autowired private ImageContributionEventDao imageContributionEventDao; + @Autowired + private StoryBookChapterDao storyBookChapterDao; + @RequestMapping(value = "/{id}", method = RequestMethod.GET) public String handleRequest(Model model, @PathVariable Long id) { logger.info("handleRequest"); // Before deleting, check if the image is used in any StoryBooks Image image = imageDao.read(id); - if (storyBookDao.readAllWithImage(image).size() > 0) { + if (storyBookDao.readAllWithImage(image).size() > 0 || storyBookChapterDao.readAllWithImage(image).size() > 0) { imageComponent.setImageModel(model, image); model.addAttribute("errorCode", "StoryBookContainImage"); From 2e379000ae2edc89e348125e9d1d67d5efaba15e Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 31 Aug 2022 21:50:48 +0100 Subject: [PATCH 3/3] 1361 Add image deletion --- src/main/java/ai/elimu/dao/StoryBookDao.java | 2 +- src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java | 4 ++-- src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java | 6 +++--- .../web/content/multimedia/image/ImageDeleteController.java | 2 +- src/test/java/ai/elimu/dao/StoryBookDaoTest.java | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/ai/elimu/dao/StoryBookDao.java b/src/main/java/ai/elimu/dao/StoryBookDao.java index 7ffdac960..c5f405bab 100644 --- a/src/main/java/ai/elimu/dao/StoryBookDao.java +++ b/src/main/java/ai/elimu/dao/StoryBookDao.java @@ -18,5 +18,5 @@ public interface StoryBookDao extends GenericDao { List readAllUnleveled() throws DataAccessException; - List readAllWithImage(Image image) throws DataAccessException; + List readAllWithCoverImage(Image image) throws DataAccessException; } diff --git a/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java b/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java index da9bbabb4..358702fc7 100644 --- a/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java +++ b/src/main/java/ai/elimu/dao/jpa/StoryBookChapterDaoJpa.java @@ -27,8 +27,8 @@ public List readAllWithImage(Image image) throws DataAccessExc return em.createQuery( "SELECT ch " + "FROM StoryBookChapter ch " + - "WHERE ch.image.id = :image ") - .setParameter("image", image.getId()) + "WHERE ch.image = :image ") + .setParameter("image", image) .getResultList(); } diff --git a/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java b/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java index 0d43c7628..178666969 100644 --- a/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java +++ b/src/main/java/ai/elimu/dao/jpa/StoryBookDaoJpa.java @@ -57,12 +57,12 @@ public List readAllUnleveled() throws DataAccessException { } @Override - public List readAllWithImage(Image image) throws DataAccessException { + public List readAllWithCoverImage(Image image) throws DataAccessException { return em.createQuery( "SELECT book " + "FROM StoryBook book " + - "WHERE book.coverImage.id = :image ") - .setParameter("image", image.getId()) + "WHERE book.coverImage = :image") + .setParameter("image", image) .getResultList(); } diff --git a/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java b/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java index 9d3a5d902..a5320f115 100644 --- a/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java +++ b/src/main/java/ai/elimu/web/content/multimedia/image/ImageDeleteController.java @@ -40,7 +40,7 @@ public String handleRequest(Model model, @PathVariable Long id) { // Before deleting, check if the image is used in any StoryBooks Image image = imageDao.read(id); - if (storyBookDao.readAllWithImage(image).size() > 0 || storyBookChapterDao.readAllWithImage(image).size() > 0) { + if (storyBookDao.readAllWithCoverImage(image).size() > 0 || storyBookChapterDao.readAllWithImage(image).size() > 0) { imageComponent.setImageModel(model, image); model.addAttribute("errorCode", "StoryBookContainImage"); diff --git a/src/test/java/ai/elimu/dao/StoryBookDaoTest.java b/src/test/java/ai/elimu/dao/StoryBookDaoTest.java index c873850c2..5fa696cc3 100644 --- a/src/test/java/ai/elimu/dao/StoryBookDaoTest.java +++ b/src/test/java/ai/elimu/dao/StoryBookDaoTest.java @@ -33,15 +33,15 @@ public void testReadByTitle() { } @Test - public void testReadAllWithImage() { + public void testReadAllWithCoverImage() { imageDao.create(ImageUtil.getImage("test read all with image")); Image image = imageDao.read("test read all with image"); - assertEquals(0, storyBookDao.readAllWithImage(image).size()); + assertEquals(0, storyBookDao.readAllWithCoverImage(image).size()); storyBookDao.create(getStoryBook("test read all with image", image)); - assertEquals(1, storyBookDao.readAllWithImage(image).size()); + assertEquals(1, storyBookDao.readAllWithCoverImage(image).size()); } private StoryBook getStoryBook(String title) {