diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/MarketplaceRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/MarketplaceRESTController.java index 04c1b78016f..4b339007494 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/MarketplaceRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/MarketplaceRESTController.java @@ -165,4 +165,72 @@ public ModelAndView saveUserRating( return new ModelAndView( "json", "rating", new MarketplaceEntryRating(Integer.parseInt(rating), review)); } + + /** + * Get all ratings done on portlets since daysBack ago. + * + * @param request + * @param daysBack - number of days back to search for portlet ratings + * @return + */ + @RequestMapping(value = "/marketplace/{daysBack}/getRatings", method = RequestMethod.GET) + public ModelAndView getPortletRatings(HttpServletRequest request, @PathVariable int daysBack) { + + Set portlets = marketplaceRatingDAO.getAllRatingsInLastXDays(daysBack); + + List ratings = new ArrayList<>(); + + for (IMarketplaceRating portlet : portlets) { + + MarketplaceEntryRating portletRating = + new MarketplaceEntryRating( + portlet.getMarketplaceRatingPK().getUserName(), + portlet.getMarketplaceRatingPK().getPortletDefinition().getName(), + portlet.getMarketplaceRatingPK().getPortletDefinition().getFName(), + portlet.getRating(), + portlet.getReview(), + portlet.getRatingDate()); + + ratings.add(portletRating); + } + + return new ModelAndView("json", "ratings", ratings); + } + + /** + * Get all ratings done on a specific portlet since daysBack ago. + * + * @param request + * @param fname - portlet fname + * @param daysBack - number of days back to search for portlet ratings + * @return + */ + @RequestMapping( + value = "/marketplace/{fname}/{daysBack}/getRatings", + method = RequestMethod.GET + ) + public ModelAndView getPortletRatings( + HttpServletRequest request, @PathVariable String fname, @PathVariable int daysBack) { + + Set portlets = + marketplaceRatingDAO.getAllRatingsForPortletInLastXDays(daysBack, fname); + + List ratings = new ArrayList<>(); + + for (IMarketplaceRating portlet : portlets) { + + MarketplaceEntryRating portletRating = + new MarketplaceEntryRating( + portlet.getMarketplaceRatingPK().getUserName(), + portlet.getMarketplaceRatingPK().getPortletDefinition().getName(), + portlet.getMarketplaceRatingPK().getPortletDefinition().getFName(), + portlet.getRating(), + portlet.getReview(), + portlet.getRatingDate()); + + ratings.add(portletRating); + } + + return new ModelAndView("json", "ratings", ratings); + } } diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/layout/MarketplaceEntryRating.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/layout/MarketplaceEntryRating.java index d9075150959..7966c6431f3 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/layout/MarketplaceEntryRating.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/layout/MarketplaceEntryRating.java @@ -14,8 +14,12 @@ */ package org.apereo.portal.rest.layout; +import java.util.Date; + public class MarketplaceEntryRating { + public MarketplaceEntryRating() {} + public MarketplaceEntryRating(int rating, String review) { this.rating = rating; this.review = review; @@ -23,6 +27,43 @@ public MarketplaceEntryRating(int rating, String review) { private int rating; private String review; + private String user; + private String portletName; + private Date ratingDate; + private String portletFName; + + public MarketplaceEntryRating( + String user, + String portletName, + String portletFName, + int rating, + String review, + Date ratingDate) { + this.user = user; + this.portletName = portletName; + this.portletFName = portletFName; + this.rating = rating; + this.review = review; + this.ratingDate = ratingDate; + } + + @Override + public String toString() { + return "MarketplaceEntryRating{" + + "rating=" + + rating + + ", review=" + + review + + ", user=" + + user + + ", portletName=" + + portletName + + ", ratingDate=" + + ratingDate + + ", portletFName=" + + portletFName + + '}'; + } public int getRating() { return rating; @@ -39,4 +80,36 @@ public String getReview() { public void setReview(String review) { this.review = review; } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPortletName() { + return portletName; + } + + public void setPortletName(String portletName) { + this.portletName = portletName; + } + + public Date getRatingDate() { + return ratingDate; + } + + public void setRatingDate(Date ratingDate) { + this.ratingDate = ratingDate; + } + + public String getPortletFName() { + return portletFName; + } + + public void setPortletFName(String portletFName) { + this.portletFName = portletFName; + } } diff --git a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/MarketplaceRESTControllerTest.java b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/MarketplaceRESTControllerTest.java index c8c06695f8a..3f48379c7d5 100644 --- a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/MarketplaceRESTControllerTest.java +++ b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/MarketplaceRESTControllerTest.java @@ -111,6 +111,28 @@ public void testGetUserRating() { Assert.assertNull(modelAndView.getModel().get("rating")); } + @Test + public void testAllPortletRatingDaysBack() { + + String remoteUser = "jdoe"; + Mockito.when(req.getRemoteUser()).thenReturn("jdoe"); + IPortletType portletType = + new PortletTypeImpl("John Doe", "http://localhost:8080/uportal/test"); + portletType.setDescription("Portlet Type"); + + PortletDefinitionImpl tempPortlet = + new PortletDefinitionImpl( + portletType, "John", "Doe", "Course", "app-id", "Courses", true); + + Mockito.when( + marketplaceService.getOrCreateMarketplacePortletDefinitionIfTheFnameExists( + remoteUser)) + .thenReturn(null); + + ModelAndView modelAndView = marketplaceRESTController.getPortletRatings(req, F_NAME, 30); + Assert.assertNull(modelAndView.getModel().get("rating")); + } + @Test public void testSaveUserRating() { String rating = "3"; diff --git a/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/dao/IMarketplaceRatingDao.java b/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/dao/IMarketplaceRatingDao.java index 1704668e67e..3811d356285 100644 --- a/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/dao/IMarketplaceRatingDao.java +++ b/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/dao/IMarketplaceRatingDao.java @@ -62,4 +62,21 @@ IMarketplaceRating createOrUpdateRating( /** Aggregates the IMarketplaceRating into IPortletDefinition */ void aggregateMarketplaceRating(); + + /** + * Get all the ratings done in the last X days. + * + * @param numberOfDaysBack - number of days to go back to find ratings + * @return collection of IMarketplaceRating - can be null + */ + Set getAllRatingsInLastXDays(int numberOfDaysBack); + + /** + * Get all the ratings done for a specific portlet in the last X days. + * + * @param numberOfDaysBack - number of days to go back to find ratings + * @param fname - portlet fname + * @return collection of IMarketplaceRating - can be null + */ + Set getAllRatingsForPortletInLastXDays(int numberOfDaysBack, String fname); } diff --git a/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/marketplace/IMarketplaceRating.java b/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/marketplace/IMarketplaceRating.java index 0c0b61134e3..2cccaebd412 100644 --- a/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/marketplace/IMarketplaceRating.java +++ b/uPortal-content/uPortal-content-portlet/src/main/java/org/apereo/portal/portlet/marketplace/IMarketplaceRating.java @@ -14,6 +14,7 @@ */ package org.apereo.portal.portlet.marketplace; +import java.util.Date; import org.apereo.portal.portlet.dao.jpa.MarketplaceRatingPK; public interface IMarketplaceRating { @@ -39,4 +40,8 @@ public interface IMarketplaceRating { * @param review a text review of the portlet */ public void setReview(String review); + + public void setRatingDate(Date ratingDate); + + public Date getRatingDate(); } diff --git a/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDao.java b/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDao.java index bb98312b062..5e875d6ef6b 100644 --- a/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDao.java +++ b/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDao.java @@ -15,6 +15,7 @@ package org.apereo.portal.portlet.dao.jpa; import com.google.common.base.Function; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -34,6 +35,7 @@ import org.apereo.portal.portlet.dao.IPortletDefinitionDao; import org.apereo.portal.portlet.marketplace.IMarketplaceRating; import org.apereo.portal.portlet.om.IPortletDefinition; +import org.joda.time.LocalDateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; @@ -117,6 +119,7 @@ public IMarketplaceRating createOrUpdateRating( temp.setMarketplaceRatingPK(tempPK); temp.setRating(rating); temp.setReview(review); + temp.setRatingDate(new Date()); return this.createOrUpdateRating(temp); } @@ -302,4 +305,82 @@ public void aggregateMarketplaceRating() { } } } + + @Override + public Set getAllRatingsForPortletInLastXDays( + int numberOfDaysBack, final String fname) { + + LocalDateTime todayMinusNumberOfDaysBack = LocalDateTime.now().minusDays(numberOfDaysBack); + + final TypedQuery query = + this.createQuery( + this.createCriteriaQuery( + new Function< + CriteriaBuilder, CriteriaQuery>() { + @Override + public CriteriaQuery apply( + CriteriaBuilder input) { + final CriteriaQuery criteriaQuery = + input.createQuery(MarketplaceRatingImpl.class); + final Root definitionRoot = + criteriaQuery.from(MarketplaceRatingImpl.class); + Predicate ratingDatePredicate = + input.greaterThanOrEqualTo( + definitionRoot.get( + "ratingDate"), + todayMinusNumberOfDaysBack.toDate()); + Predicate conditionPortlet = + input.equal( + definitionRoot + .get("marketplaceRatingPK") + .get("portletDefinition"), + portletDefinitionDao + .getPortletDefinitionByFname( + fname)); + Predicate allConditions = + input.and(conditionPortlet, ratingDatePredicate); + criteriaQuery.select(definitionRoot).where(allConditions); + + return criteriaQuery; + } + })); + + return new HashSet(query.getResultList()); + } + + @Override + @PortalTransactionalReadOnly + @OpenEntityManager(unitName = PERSISTENCE_UNIT_NAME) + public Set getAllRatingsInLastXDays(int numberOfDaysBack) { + + LocalDateTime todayMinusNumberOfDaysBack = LocalDateTime.now().minusDays(numberOfDaysBack); + + final TypedQuery query = + this.createQuery( + this.createCriteriaQuery( + new Function< + CriteriaBuilder, CriteriaQuery>() { + @Override + public CriteriaQuery apply( + CriteriaBuilder input) { + final CriteriaQuery criteriaQuery = + input.createQuery(MarketplaceRatingImpl.class); + final Root definitionRoot = + criteriaQuery.from(MarketplaceRatingImpl.class); + Predicate ratingDatePredicate = + input.greaterThanOrEqualTo( + definitionRoot.get( + "ratingDate"), + todayMinusNumberOfDaysBack.toDate()); + + criteriaQuery + .select(definitionRoot) + .where(ratingDatePredicate); + + return criteriaQuery; + } + })); + + return new HashSet(query.getResultList()); + } } diff --git a/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/MarketplaceRatingImpl.java b/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/MarketplaceRatingImpl.java index 76bdeecc86a..505f09cf5e9 100644 --- a/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/MarketplaceRatingImpl.java +++ b/uPortal-web/src/main/java/org/apereo/portal/portlet/dao/jpa/MarketplaceRatingImpl.java @@ -14,6 +14,7 @@ */ package org.apereo.portal.portlet.dao.jpa; +import java.util.Date; import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; @@ -33,6 +34,9 @@ class MarketplaceRatingImpl implements IMarketplaceRating { @Column(name = "REVIEW", length = REVIEW_MAX_LENGTH) private String review; + @Column(name = "RATINGDATE") + private Date ratingDate; + @Override public MarketplaceRatingPK getMarketplaceRatingPK() { return marketplaceRatingPK; @@ -69,12 +73,21 @@ public void setRating(int rating) { this.rating = rating; } + public Date getRatingDate() { + return ratingDate; + } + + public void setRatingDate(Date ratingDate) { + this.ratingDate = ratingDate; + } + @Override public String toString() { return new ToStringBuilder(this) .append("RatingPK: ", this.marketplaceRatingPK) .append("Rating: ", this.rating) .append("Review: ", this.review) + .append("Date: ", this.ratingDate) .toString(); } } diff --git a/uPortal-webapp/src/test/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDaoTest.java b/uPortal-webapp/src/test/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDaoTest.java index 5fa3c3af43d..d1f3d56b174 100644 --- a/uPortal-webapp/src/test/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDaoTest.java +++ b/uPortal-webapp/src/test/java/org/apereo/portal/portlet/dao/jpa/JpaMarketplaceRatingDaoTest.java @@ -18,6 +18,8 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import java.util.Calendar; +import java.util.Date; import java.util.List; import java.util.Random; import java.util.Set; @@ -54,6 +56,8 @@ public class JpaMarketplaceRatingDaoTest extends BasePortalJpaDaoTest { private final Random random = new Random(); + private final int TEST_DATE_INCREMENT = 20; + @Before public void setup() { List personList = localAccountDao.getAllAccounts(); @@ -147,6 +151,7 @@ public Object call() throws Exception { ratingPK.setPortletDefinition((PortletDefinitionImpl) portlet); ratingPK.setUserName(person.getName()); rating.setMarketplaceRatingPK(ratingPK); + rating.setRatingDate(new Date()); marketplaceRatingDao.createOrUpdateRating(rating); } } @@ -218,6 +223,7 @@ public Object call() throws Exception { ratingPK.setPortletDefinition((PortletDefinitionImpl) portlet); ratingPK.setUserName(person.getName()); rating.setMarketplaceRatingPK(ratingPK); + rating.setRatingDate(new Date()); marketplaceRatingDao.createOrUpdateRating(rating); } } @@ -262,6 +268,7 @@ public Object call() throws Exception { ratingPK.setPortletDefinition((PortletDefinitionImpl) portlet); ratingPK.setUserName(person.getName()); rating.setMarketplaceRatingPK(ratingPK); + rating.setRatingDate(new Date()); marketplaceRatingDao.createOrUpdateRating(rating); } } @@ -279,4 +286,133 @@ public Object call() throws Exception { } }); } + + @Test + public void testGetRatingsLastXDays() { + // Easy Test Can we make every combination of portlet and user rating + this.execute( + new Callable() { + @Override + public Object call() throws Exception { + + Calendar today = Calendar.getInstance(); + + List portletList = + portletDefinitionDao.getPortletDefinitions(); + List personList = localAccountDao.getAllAccounts(); + assertNotEquals(portletList.size(), 0); + assertNotEquals(personList.size(), 0); + int numberOfDaysBack = 1; + for (IPortletDefinition portlet : portletList) { + + for (ILocalAccountPerson person : personList) { + today.add(Calendar.DAY_OF_YEAR, 0 - numberOfDaysBack); + MarketplaceRatingImpl rating = new MarketplaceRatingImpl(); + int starRating = + random.nextInt(MarketplaceRatingImpl.MAX_RATING) + 1; + rating.setRating(starRating); + MarketplaceRatingPK ratingPK = new MarketplaceRatingPK(); + ratingPK.setPortletDefinition((PortletDefinitionImpl) portlet); + ratingPK.setUserName(person.getName()); + rating.setMarketplaceRatingPK(ratingPK); + rating.setRatingDate(today.getTime()); + rating.setReview( + "comment for " + + ratingPK.getPortletDefinition().getFName()); + marketplaceRatingDao.createOrUpdateRating(rating); + numberOfDaysBack = numberOfDaysBack + TEST_DATE_INCREMENT; + } + } + return null; + } + }); + // Now let's retrieve our objects + this.execute( + new Callable() { + @Override + public Object call() throws Exception { + + int daysBack = 7; + Set ratingList = + marketplaceRatingDao.getAllRatingsInLastXDays(daysBack); + assertEquals(ratingList.size(), 1); + + daysBack = 30; + ratingList = marketplaceRatingDao.getAllRatingsInLastXDays(daysBack); + assertEquals(ratingList.size(), 2); + + daysBack = 5000; + ratingList = marketplaceRatingDao.getAllRatingsInLastXDays(daysBack); + assertEquals(ratingList.size(), 4); + + return null; + } + }); + } + + @Test + public void testGetAllRatingsForPortletInLastXDays() { + // Let's create some ratings + this.execute( + new Callable() { + @Override + public Object call() throws Exception { + + Calendar today = Calendar.getInstance(); + + List portletList = + portletDefinitionDao.getPortletDefinitions(); + List personList = localAccountDao.getAllAccounts(); + assertNotEquals(portletList.size(), 0); + assertNotEquals(personList.size(), 0); + int numberOfDaysBack = 1; + for (IPortletDefinition portlet : portletList) { + + for (ILocalAccountPerson person : personList) { + today.add(Calendar.DAY_OF_YEAR, 0 - numberOfDaysBack); + System.out.println( + "Testing get ratings using " + + today.getTime() + + " for portlet creation date. Porlet is " + + portlet.getFName()); + MarketplaceRatingImpl rating = new MarketplaceRatingImpl(); + int starRating = + random.nextInt(MarketplaceRatingImpl.MAX_RATING) + 1; + rating.setRating(starRating); + MarketplaceRatingPK ratingPK = new MarketplaceRatingPK(); + ratingPK.setPortletDefinition((PortletDefinitionImpl) portlet); + ratingPK.setUserName(person.getName()); + rating.setMarketplaceRatingPK(ratingPK); + rating.setRatingDate(today.getTime()); + rating.setReview( + "comment for " + + ratingPK.getPortletDefinition().getFName()); + marketplaceRatingDao.createOrUpdateRating(rating); + numberOfDaysBack = numberOfDaysBack + TEST_DATE_INCREMENT; + } + } + return null; + } + }); + // Now let's test getting a rating for specific portlet and specific number of + // days back + this.execute( + new Callable() { + @Override + public Object call() throws Exception { + int daysBack = 7; + Set ratingList = + marketplaceRatingDao.getAllRatingsForPortletInLastXDays( + daysBack, "fname1"); + assertEquals(ratingList.size(), 1); + + daysBack = 30; + ratingList = + marketplaceRatingDao.getAllRatingsForPortletInLastXDays( + daysBack, "fname1"); + assertEquals(ratingList.size(), 2); + return null; + } + }); + } }