diff --git a/source/java/org/alfresco/repo/rating/AllRatingTests.java b/source/java/org/alfresco/repo/rating/AllRatingTests.java new file mode 100644 index 0000000000..440beb33ea --- /dev/null +++ b/source/java/org/alfresco/repo/rating/AllRatingTests.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.rating; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * This class is a holder for the various test classes associated with the Rating Service. + * It is not (at the time of writing) intended to be incorporated into the automatic build + * which will find the various test classes and run them individually. + * + * @author Neil McErlean + * @since 3.4 + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + RatingNodePropertiesTest.class, + RatingServiceIntegrationTest.class +}) +public class AllRatingTests +{ + // Intentionally empty +} diff --git a/source/java/org/alfresco/repo/rating/RatingNodeProperties.java b/source/java/org/alfresco/repo/rating/RatingNodeProperties.java new file mode 100644 index 0000000000..8519921276 --- /dev/null +++ b/source/java/org/alfresco/repo/rating/RatingNodeProperties.java @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.rating; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.rating.RatingServiceException; +import org.alfresco.service.namespace.QName; + +/** + * The cm:rating content type defines the properties which are used in + * managing user-applied ratings. See contentModel.xml for details. + *

+ * Briefly, these properties are multi-valued where a 'slice' through the property + * set constitutes an individual user-applied rating. So if we were to take the value + * at index n of each multi-valued property, that would represent the + * score, appliedAt and scheme for one rating. + *

+ * This class simplifies and centralises the handling of these property sets. + * + * @author Neil McErlean + * @since 3.4 + */ +public class RatingNodeProperties +{ + // These lists are declared as the concrete type 'ArrayList' as they must implement Serializable + private final ArrayList schemes; + private final ArrayList scores; + private final ArrayList dates; + + public RatingNodeProperties(List schemes, List scores, List dates) + { + // No null lists. + if (schemes == null) schemes = new ArrayList(); + if (scores == null) scores = new ArrayList(); + if (dates == null) dates = new ArrayList(); + + // All lists must be the same length. + if (scores.size() != schemes.size() || dates.size() != schemes.size()) + { + throw new RatingServiceException("Rating node properties have unequal list lengths: " + + schemes.size() + " " + scores.size() + " " + dates.size()); + } + + // Copy all these data to ensure no leakage of this class' state into the original properties. + this.schemes = new ArrayList(schemes.size()); + for (String s : schemes) + this.schemes.add(s); + + this.scores = new ArrayList(scores.size()); + for (Integer i : scores) + this.scores.add(i); + + this.dates = new ArrayList(dates.size()); + // We can't copy Dates straight over as Date objects are mutable, so clone. + for (Date d : dates) + this.dates.add((Date)d.clone()); + } + + /** + * This factory method creates a new {@link RatingNodeProperties} from the specified + * properties map. + * @param props + * @return + */ + @SuppressWarnings("unchecked") + public static RatingNodeProperties createFrom(Map props) + { + List schemes = (List) props.get(ContentModel.PROP_RATING_SCHEME); + List scores = (List)props.get(ContentModel.PROP_RATING_SCORE); + List dates = (List) props.get(ContentModel.PROP_RATED_AT); + + return new RatingNodeProperties(schemes, scores, dates); + } + + /** + * This method returns the number of ratings currently held by the multivalued properties. + * @return the number of ratings. + */ + public int size() + { + return this.schemes.size(); + } + + /** + * This method gets the {@link Rating} for the specified index. + * @param index + * @return + */ + public RatingStruct getRatingAt(int index) + { + String scheme = this.schemes.get(index); + int score = this.scores.get(index); + Date d = this.dates.get(index); + return new RatingStruct(scheme, score, d); + } + + /** + * This method appends a new rating in the specified schemeName. The ratedAt date + * will be set to 'now'. + * + * @param schemeName the scheme name. + * @param score the score. + */ + public void appendRating(String schemeName, int score) + { + this.schemes.add(schemeName); + this.scores.add(score); + this.dates.add(new Date()); + } + + /** + * This method sets the rating at the specified index. + * Note that to persist these changes, {@link RatingNodeProperties#toNodeProperties()} + * can be called to retrieve a property map which should then be saved via the + * {@link NodeService} in the usual way. + *

+ * The ratedAt property will be automatically set to 'now'. + * @param index the index at which the change is to be made. + * @param scheme the new rating scheme name. + * @param score the new rating score. + */ + public void setRatingAt(int index, String scheme, int score) + { + this.schemes.set(index, scheme); + this.scores.set(index, score); + this.dates.set(index, new Date()); + } + + /** + * This method removes the rating at the specified index. + * @param index + * @return the removed rating data. + */ + public RatingStruct removeRatingAt(int index) + { + String removedScheme = this.schemes.remove(index); + int removedScore = this.scores.remove(index); + Date removedDate = this.dates.remove(index); + + return new RatingStruct(removedScheme, removedScore, removedDate); + } + + /** + * This method returns all ratings as a List of {@link RatingStruct} objects. + * @return + */ + public List getAllRatings() + { + List result = new ArrayList(schemes.size()); + for (int i = 0; i < schemes.size(); i++) + { + result.add(new RatingStruct(schemes.get(i), scores.get(i), dates.get(i))); + } + return result; + } + + /** + * This method gets the rating which has the specified schemeName. There should only + * be one such rating. + * @param schemeName + * @return the requested {@link RatingStruct} if there is one, else null. + */ + public RatingStruct getRating(String schemeName) + { + for (int i = 0; i < schemes.size(); i ++) + { + if (schemes.get(i).equals(schemeName)) + { + return new RatingStruct(schemes.get(i), scores.get(i), dates.get(i)); + } + } + return null; + } + + /** + * This method returns the index of the rating with the specified scheme name, if there + * is such a rating. + * @param schemeName + * @return the index of the specified rating if there is one, else -1. + */ + public int getIndexOfRating(String schemeName) + { + for (int i = 0; i < schemes.size(); i ++) + { + if (schemes.get(i).equals(schemeName)) + { + return i; + } + } + return -1; + } + + /** + * This method converts this {@link RatingNodeProperties} object into a Map of + * properties consistent with the Alfresco ratings content model. See contentModel.xml. + * These can then be set in the database via the {@link NodeService} in the usual way. + * @return + */ + public Map toNodeProperties() + { + Map results = new HashMap(); + results.put(ContentModel.PROP_RATING_SCHEME, this.schemes); + results.put(ContentModel.PROP_RATING_SCORE, this.scores); + results.put(ContentModel.PROP_RATED_AT, this.dates); + + return results; + } + + /** + * A simple struct class to help in handling the related properties within a cm:rating. + * @author Neil Mc Erlean. + * + */ + public class RatingStruct + { + private String scheme; + private int score; + private Date date; + + public RatingStruct(String scheme, int score, Date d) + { + RatingStruct.this.scheme = scheme; + RatingStruct.this.score = score; + RatingStruct.this.date = d; + } + + public String getScheme() + { + return scheme; + } + + public int getScore() + { + return score; + } + + public Date getDate() + { + return date; + } + + @Override + public boolean equals(Object thatObj) + { + if (thatObj == null || thatObj.getClass().equals(RatingStruct.this.getClass()) == false) + { + return false; + } + RatingStruct that = (RatingStruct)thatObj; + return RatingStruct.this.scheme.equals(that.scheme) && + RatingStruct.this.score == that.score && + RatingStruct.this.date.equals(that.date); + } + + @Override + public int hashCode() + { + return scheme.hashCode() + 7 * score + 11 * date.hashCode(); + } + + @Override + public String toString() + { + StringBuilder msg = new StringBuilder(); + msg.append(RatingStruct.this.getClass().getSimpleName()) + .append(" '").append(scheme).append("' ") + .append(score).append(" ").append(date); + return msg.toString(); + } +} +} diff --git a/source/java/org/alfresco/repo/rating/RatingNodePropertiesTest.java b/source/java/org/alfresco/repo/rating/RatingNodePropertiesTest.java new file mode 100644 index 0000000000..ff1203a3a7 --- /dev/null +++ b/source/java/org/alfresco/repo/rating/RatingNodePropertiesTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.rating; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.rating.RatingNodeProperties.RatingStruct; +import org.alfresco.service.namespace.QName; +import org.junit.Before; +import org.junit.Test; + +/** + * Unit Test class for {@link RatingNodeProperties}. + * + * @author Neil Mc Erlean + * @since 3.4 + */ +public class RatingNodePropertiesTest +{ + private static final String LIKE = "like"; + private static final String FIVESTAR = "fivestar"; + + // These are declared as ArrayLists in order to be Serializable. + private ArrayList testSchemes; + private ArrayList testScores; + private ArrayList testDates; + private RatingNodeProperties testProps; + + @Before public void initTestData() + { + testSchemes = new ArrayList(); + testScores = new ArrayList(); + testDates = new ArrayList(); + // These correspond to two ratings: + // '1' in the 'like' scheme at 'now'. + // '5' in the 'fivestar' scheme at 'now'. + testSchemes.add(LIKE); + testSchemes.add(FIVESTAR); + + testScores.add(1); + testScores.add(5); + + testDates.add(new Date()); + testDates.add(new Date()); + + Map alfrescoStyleProps = new HashMap(); + alfrescoStyleProps.put(ContentModel.PROP_RATING_SCHEME, testSchemes); + alfrescoStyleProps.put(ContentModel.PROP_RATING_SCORE, testScores); + alfrescoStyleProps.put(ContentModel.PROP_RATED_AT, testDates); + + testProps = RatingNodeProperties.createFrom(alfrescoStyleProps); + + } + + /** + * This test method checks that constructing a RatingNodeProperties with null-valued + * property lists works. + */ + @Test public void noNullPropertyLists() throws Exception + { + List schemes = null; + List scores = null; + List dates = null; + RatingNodeProperties nullProps = new RatingNodeProperties(schemes, scores, dates); + + assertEquals(0, nullProps.size()); + } + + @Test public void constructAndAccessRatings() throws Exception + { + assertEquals(2, testProps.size()); + assertEquals(2, testProps.getAllRatings().size()); + + assertEquals(0, testProps.getIndexOfRating(LIKE)); + assertEquals(-1, testProps.getIndexOfRating("noSuchScheme")); + + final RatingStruct firstRating = testProps.getRatingAt(0); + assertEquals(LIKE, firstRating.getScheme()); + assertEquals(1, firstRating.getScore()); + final Date recoveredLikeDate = firstRating.getDate(); + assertNotNull(recoveredLikeDate); + + final RatingStruct secondRating = testProps.getRatingAt(1); + assertEquals(FIVESTAR, secondRating.getScheme()); + assertEquals(5, secondRating.getScore()); + final Date recoveredSecondDate = secondRating.getDate(); + assertNotNull(recoveredSecondDate); + + RatingStruct l = testProps.getRating(LIKE); + assertNotNull(l); + assertEquals(LIKE, l.getScheme()); + assertEquals(1, l.getScore()); + assertEquals(recoveredLikeDate, l.getDate()); + } + + @Test public void appendRating() + { + // Check all is right before we start + assertEquals(2, testProps.size()); + + testProps.appendRating("appended", 10); + assertEquals(3, testProps.size()); + + assertNotNull(testProps.getRating(LIKE)); + assertNotNull(testProps.getRating(FIVESTAR)); + assertNotNull(testProps.getRating("appended")); + } + + @Test public void removeRating() + { + // Check all is right before we start + assertEquals(2, testProps.size()); + + // Remove the first rating - should be 'like' + + testProps.removeRatingAt(0); + assertEquals(1, testProps.size()); + + // Now 'like' should be gone, but 'fivestar' should still be there. + assertNull(testProps.getRating(LIKE)); + assertNotNull(testProps.getRating(FIVESTAR)); + } + + @Test public void replaceRating() + { + // Check all is right before we start + assertEquals(2, testProps.size()); + + // Replace the first rating - should be 'like' + + // There's no such rating scheme as 'foo' but for this unit test it doesn't matter. + testProps.setRatingAt(0, "foo", 42); + assertEquals(2, testProps.size()); + + // Now 'like' should be replaced by 'foo'. + assertNull(testProps.getRating(LIKE)); + assertNotNull(testProps.getRating(FIVESTAR)); + final RatingStruct fooRating = testProps.getRating("foo"); + assertNotNull(fooRating); + assertEquals(42, fooRating.getScore()); + } + + @SuppressWarnings("unchecked") + @Test public void extractAlfrescoNodeProperties() + { + Map alfProps = this.testProps.toNodeProperties(); + assertNotNull(alfProps); + final int numberOfProperties = 3; + assertEquals(numberOfProperties, alfProps.size()); + final List ratingSchemes = (List)alfProps.get(ContentModel.PROP_RATING_SCHEME); + final List ratingScores = (List)alfProps.get(ContentModel.PROP_RATING_SCORE); + final List ratingDates = (List)alfProps.get(ContentModel.PROP_RATED_AT); + final int numberOfRatings = 2; + assertEquals(numberOfRatings, ratingSchemes.size()); + assertEquals(numberOfRatings, ratingScores.size()); + assertEquals(numberOfRatings, ratingDates.size()); + assertEquals(Arrays.asList(new String[]{LIKE, FIVESTAR}), ratingSchemes); + assertEquals(Arrays.asList(new Integer[]{1, 5}), ratingScores); + // No Date checks + } +} diff --git a/source/java/org/alfresco/repo/rating/RatingServiceImpl.java b/source/java/org/alfresco/repo/rating/RatingServiceImpl.java index 8ca2ab7728..80f89c2174 100644 --- a/source/java/org/alfresco/repo/rating/RatingServiceImpl.java +++ b/source/java/org/alfresco/repo/rating/RatingServiceImpl.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import org.alfresco.model.ContentModel; +import org.alfresco.repo.rating.RatingNodeProperties.RatingStruct; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.rating.Rating; import org.alfresco.service.cmr.rating.RatingScheme; @@ -104,16 +105,23 @@ public class RatingServiceImpl implements RatingService private boolean isCurrentUserNodeCreator(NodeRef targetNode) { final String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); - // TODO Is creator the right property here? + // TODO Is creator the right property to use here? Serializable creator = nodeService.getProperty(targetNode, ContentModel.PROP_CREATOR); return currentUser.equals(creator); } - @SuppressWarnings("unchecked") private void applyRating(NodeRef targetNode, int rating, String ratingSchemeName, final String userName) throws RatingServiceException { - //TODO More logging. + if (log.isDebugEnabled()) + { + StringBuilder msg = new StringBuilder(); + msg.append("Applying rating ") + .append(rating).append(" in scheme ") + .append(ratingSchemeName).append(" as user ") + .append(userName).append(" on ").append(targetNode); + log.debug(msg.toString()); + } // Sanity check the rating scheme being used and the rating being applied. final RatingScheme ratingScheme = this.getRatingScheme(ratingSchemeName); @@ -142,7 +150,6 @@ public class RatingServiceImpl implements RatingService // These are multivalued properties. Map ratingProps = new HashMap(); - ratingProps.put(ContentModel.PROP_RATING_SCORE, new Integer[]{rating}); ratingProps.put(ContentModel.PROP_RATING_SCORE, toSerializableList(new Integer[]{rating})); ratingProps.put(ContentModel.PROP_RATED_AT, toSerializableList(new Date[]{new Date()})); ratingProps.put(ContentModel.PROP_RATING_SCHEME, toSerializableList(new String[]{ratingSchemeName})); @@ -159,27 +166,19 @@ public class RatingServiceImpl implements RatingService NodeRef myPreviousRatingsNode = myRatingChildren.get(0).getChildRef(); Map existingProps = nodeService.getProperties(myPreviousRatingsNode); - List existingRatingSchemes = (List)existingProps.get(ContentModel.PROP_RATING_SCHEME); - List existingRatingScores = (List)existingProps.get(ContentModel.PROP_RATING_SCORE); - List existingRatingDates = (List)existingProps.get(ContentModel.PROP_RATED_AT); - - //TODO These should all be the same length lists. Log if not. + RatingNodeProperties ratingProps = RatingNodeProperties.createFrom(existingProps); // If the schemes list already contains an entry matching the rating we're setting // we need to delete it and then delete the score and date at the corresponding indexes. - int indexOfExistingRating = existingRatingSchemes.indexOf(ratingSchemeName); + int indexOfExistingRating = ratingProps.getIndexOfRating(ratingSchemeName); if (indexOfExistingRating != -1) { - existingRatingSchemes.remove(indexOfExistingRating); - existingRatingScores.remove(indexOfExistingRating); - existingRatingDates.remove(indexOfExistingRating); + ratingProps.removeRatingAt(indexOfExistingRating); } - existingRatingSchemes.add(ratingSchemeName); - existingRatingScores.add(rating); - existingRatingDates.add(new Date()); + ratingProps.appendRating(ratingSchemeName, rating); - nodeService.setProperties(myPreviousRatingsNode, existingProps); + nodeService.setProperties(myPreviousRatingsNode, ratingProps.toNodeProperties()); } } @@ -198,7 +197,6 @@ public class RatingServiceImpl implements RatingService return this.getRating(targetNode, ratingSchemeName, currentUser); } - @SuppressWarnings("unchecked") private Rating getRating(NodeRef targetNode, String ratingSchemeName, String user) { List ratingChildren = getRatingNodeChildren(targetNode, user); @@ -212,10 +210,10 @@ public class RatingServiceImpl implements RatingService // Take the last node pertaining to the current user. ChildAssociationRef lastChild = ratingChildren.get(ratingChildren.size() - 1); Map properties = nodeService.getProperties(lastChild.getChildRef()); - + // Find the index of the rating scheme we're interested in. - RatingScheme ratingScheme = getRatingScheme(ratingSchemeName); - int index = findIndexOfRatingScheme(properties, ratingScheme); + RatingNodeProperties ratingProps = RatingNodeProperties.createFrom(properties); + int index = ratingProps.getIndexOfRating(ratingSchemeName); if (index == -1) { // There is no rating in this scheme by the specified user. @@ -224,25 +222,17 @@ public class RatingServiceImpl implements RatingService else { // There is a rating and the associated data are at the index'th place in each multivalued property. - List ratingScores = (List)properties.get(ContentModel.PROP_RATING_SCORE); - List ratingDates = (List)properties.get(ContentModel.PROP_RATED_AT); + RatingStruct ratingStruct = ratingProps.getRatingAt(index); - Rating result = new Rating(ratingScheme, - ratingScores.get(index), + Rating result = new Rating(getRatingScheme(ratingStruct.getScheme()), + ratingStruct.getScore(), user, - ratingDates.get(index)); + ratingStruct.getDate()); return result; } //TODO Don't forget that it is possible on read to have out-of-range ratings. } - - @SuppressWarnings("unchecked") - private int findIndexOfRatingScheme(Map properties, RatingScheme scheme) - { - List ratingSchemes = (List)properties.get(ContentModel.PROP_RATING_SCHEME); - return ratingSchemes.indexOf(scheme.getName()); - } /* * (non-Javadoc) @@ -255,7 +245,6 @@ public class RatingServiceImpl implements RatingService return removeRating(targetNode, ratingScheme, currentUser); } - @SuppressWarnings("unchecked") private Rating removeRating(NodeRef targetNode, String ratingSchemeName, String user) { List ratingChildren = getRatingNodeChildren(targetNode, user); @@ -269,8 +258,9 @@ public class RatingServiceImpl implements RatingService Map properties = nodeService.getProperties(lastChild.getChildRef()); // Find the index of the rating scheme we're interested in. - RatingScheme ratingScheme = getRatingScheme(ratingSchemeName); - int index = this.findIndexOfRatingScheme(properties, ratingScheme); + RatingNodeProperties ratingProps = RatingNodeProperties.createFrom(properties); + + int index = ratingProps.getIndexOfRating(ratingSchemeName); if (index == -1) { // There is no rating in this scheme by the specified user. @@ -279,16 +269,10 @@ public class RatingServiceImpl implements RatingService else { // There is a rating and the associated data are at the index'th place in each property. - List ratingScores = (List)properties.get(ContentModel.PROP_RATING_SCORE); - List ratingDates = (List)properties.get(ContentModel.PROP_RATED_AT); - List ratingSchemes = (List)properties.get(ContentModel.PROP_RATING_SCHEME); + RatingStruct removed = ratingProps.removeRatingAt(index); - Integer oldScore = ratingScores.remove(index); - Date oldDate = ratingDates.remove(index); - String oldScheme = ratingSchemes.remove(index); - - return new Rating(this.getRatingScheme(oldScheme), - oldScore, user, oldDate); + return new Rating(this.getRatingScheme(removed.getScheme()), + removed.getScore(), user, removed.getDate()); } } @@ -320,7 +304,7 @@ public class RatingServiceImpl implements RatingService return result; } - // TODO We can at least amagamate these into one looping call. + // TODO We can at least amalgamate these into one looping call. public float getAverageRating(NodeRef targetNode, String ratingSchemeName) { //TODO Put these in the db as properties? @@ -405,7 +389,6 @@ public class RatingServiceImpl implements RatingService * @param ratingNode * @return */ - @SuppressWarnings("unchecked") private List getRatingsFrom(NodeRef ratingNode) { // The appliedBy is encoded in the parent assoc qname. @@ -414,16 +397,15 @@ public class RatingServiceImpl implements RatingService String appliedBy = parentAssoc.getQName().getLocalName(); Map properties = nodeService.getProperties(ratingNode); - List ratingSchemes = (List)properties.get(ContentModel.PROP_RATING_SCHEME); - List ratingScores = (List)properties.get(ContentModel.PROP_RATING_SCORE); - List ratingDates = (List)properties.get(ContentModel.PROP_RATED_AT); + RatingNodeProperties ratingProps = RatingNodeProperties.createFrom(properties); - List result = new ArrayList(ratingSchemes.size()); - for (int i = 0; i < ratingSchemes.size(); i++) + List result = new ArrayList(ratingProps.size()); + for (int i = 0; i < ratingProps.size(); i++) { - final String schemeName = ratingSchemes.get(i); + final String schemeName = ratingProps.getRatingAt(i).getScheme(); RatingScheme scheme = getRatingScheme(schemeName); - result.add(new Rating(scheme, ratingScores.get(i), appliedBy, ratingDates.get(i))); + result.add(new Rating(scheme, ratingProps.getRatingAt(i).getScore(), + appliedBy, ratingProps.getRatingAt(i).getDate())); } return result; }