/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.ratings.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.DocumentReferenceResolver;
import org.xwiki.model.reference.EntityReferenceSerializer;
import org.xwiki.ratings.Rating;
import org.xwiki.ratings.RatingsException;
import org.xwiki.ratings.RatingsManager;
import org.xwiki.ratings.UpdateRatingEvent;
import org.xwiki.ratings.UpdatingRatingEvent;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
/**
* @version $Id: e94a34720619d169a99f5653860101e177d6ad85 $
* @see RatingsManager
* @see AbstractRatingsManager
* @since 6.4M3
*/
@Component
@Singleton
@Named("separate")
public class SeparatePageRatingsManager extends AbstractRatingsManager
{
public static final String SEPARATERATINGS_CONFIG_PARAM_PREFIX = "xwiki.ratings.separatepage.";
public static final String SEPARATERATINGS_CONFIG_FIELDNAME_SEPARATEPAGE_SPACE = "space";
public static final String SEPARATERATINGS_CONFIG_FIELDNAME_SEPARATEPAGE_RATINGS_SPACE_PER_SPACE =
"ratingsSpacePerSpace";
@Inject
private Logger LOGGER;
@Inject
@Named("user/current")
protected DocumentReferenceResolver<String> userReferenceResolver;
@Inject
@Named("compactwiki")
protected EntityReferenceSerializer<String> entityReferenceSerializer;
/**
* SeparatePageRatingsManager constructor.
*/
public SeparatePageRatingsManager()
{
super();
}
/**
* Gets the ratings space name.
*
* @param documentRef reference to the document with which the ratings are associated
* @return the ratings space name
*/
public String getRatingsSpaceName(DocumentReference documentRef)
{
String ratingsSpaceName = getXWiki().Param("xwiki.ratings.separatepagemanager.spacename", "");
ratingsSpaceName =
getXWiki().getXWikiPreference("ratings_separatepagemanager_spacename", ratingsSpaceName, getXWikiContext());
return getRatingsConfiguration().getConfigurationParameter(documentRef,
RatingsManager.RATINGS_CONFIG_CLASS_FIELDNAME_STORAGE_SPACE, ratingsSpaceName);
}
/**
* Gets whether to associate a different space for every space which is ratable.
*
* @param documentRef reference to the document with which the ratings are associated
* @return whether to associate a different space for every space which is ratable
*/
public boolean hasRatingsSpaceForeachSpace(DocumentReference documentRef)
{
String result = getXWiki().Param("xwiki.ratings.separatepagemanager.ratingsspaceforeachspace", "0");
result =
getXWiki().getXWikiPreference("ratings_separatepagemanager_ratingsspaceforeachspace", result,
getXWikiContext());
return (getRatingsConfiguration().getConfigurationParameter(documentRef,
RatingsManager.RATINGS_CONFIG_CLASS_FIELDNAME_STORAGE_SEPARATE_SPACES, result) == "1");
}
/**
* Saves the rating.
*
* @param rating a Rating object
* @throws RatingsException when an error occurs while saving the rating
*/
protected void saveRating(Rating rating) throws RatingsException
{
try {
rating.save();
} catch (XWikiException e) {
throw new RatingsException(e);
}
}
@Override
public Rating setRating(DocumentReference documentRef, DocumentReference author, int vote) throws RatingsException
{
Rating rating = getRating(documentRef, author);
int oldVote;
if (rating == null) {
oldVote = 0;
rating = new SeparatePageRating(documentRef, author, vote, getXWikiContext(), this);
} else {
oldVote = rating.getVote();
rating.setVote(vote);
rating.setDate(new Date());
}
// Indicate that we start modifying the rating
this.observationManager.notify(new UpdatingRatingEvent(documentRef, rating, oldVote), null);
boolean updateFailed = true;
try {
// saving rating
rating.save();
// update the average rating
updateAverageRatings(documentRef, rating, oldVote);
updateFailed = false;
} finally {
if (updateFailed) {
// Indicate that the we start modifying the rating
this.observationManager.notify(new UpdatingRatingEvent(documentRef, rating, oldVote), null);
} else {
// Indicate that we finished updating the rating
this.observationManager.notify(new UpdateRatingEvent(documentRef, rating, oldVote), null);
}
}
return rating;
}
@Override
public List<Rating> getRatings(DocumentReference documentRef, int start, int count, boolean asc)
throws RatingsException
{
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Calling separate page manager code for ratings");
}
String sql = ", BaseObject as obj, StringProperty as parentprop where doc.fullName=obj.name and obj.className=?"
+ " and obj.id=parentprop.id.id and parentprop.id.name=?" + " and parentprop.value=?"
+ " and obj.name not in (select obj2.name from BaseObject as obj2, StringProperty as statusprop where obj2.className=?"
+ " and obj2.id=statusprop.id.id and statusprop.id.name=? and (statusprop.value=? or statusprop.value= ?) and obj.id=obj2.id) order by doc.date "
+ (asc ? "asc" : "desc");
List<?> params = new ArrayList<String>(Arrays.asList(getRatingsClassName(), RATING_CLASS_FIELDNAME_PARENT,
entityReferenceSerializer.serialize(documentRef), getRatingsClassName(), "status", "moderated", "refused"));
List<Rating> ratings = new ArrayList<Rating>();
try {
List<DocumentReference> ratingPageReferenceList =
getXWikiContext().getWiki().getStore().searchDocumentReferences(sql, params, getXWikiContext());
for (DocumentReference ratingPageReference : ratingPageReferenceList) {
ratings.add(getRatingFromDocument(documentRef,
getXWiki().getDocument(ratingPageReference, getXWikiContext())));
}
} catch (XWikiException e) {
throw new RatingsException(e);
}
return ratings;
}
@Override
public Rating getRating(DocumentReference documentRef, int id) throws RatingsException
{
String sql = ", BaseObject as obj, StringProperty as parentprop where doc.fullName=obj.name and obj.className=?"
+ " and obj.id=parentprop.id.id and parentprop.id.name=?" + " and parentprop.value=?"
+ " and obj.name not in (select obj2.name from BaseObject as obj2, StringProperty as statusprop where obj2.className=?"
+ " and obj2.id=statusprop.id.id and statusprop.id.name=? and (statusprop.value=? or statusprop.value=?) and obj.id=obj2.id) order by doc.date desc";
List<?> params = new ArrayList<String>(Arrays.asList(getRatingsClassName(), RATING_CLASS_FIELDNAME_PARENT,
entityReferenceSerializer.serialize(documentRef), getRatingsClassName(), "status", "moderated", "refused"));
try {
List<DocumentReference> ratingPageReferenceList =
getXWikiContext().getWiki().getStore().searchDocumentReferences(sql, 1, id, params, getXWikiContext());
if ((ratingPageReferenceList == null) || (ratingPageReferenceList.size() == 0)) {
return null;
} else {
return new SeparatePageRatingsManager().getRatingFromDocument(documentRef,
getXWiki().getDocument(ratingPageReferenceList.get(0), getXWikiContext()));
}
} catch (XWikiException e) {
throw new RatingsException(e);
}
}
@Override
public Rating getRating(DocumentReference documentRef, DocumentReference author) throws RatingsException
{
try {
for (Rating rating : getRatings(documentRef, 0, 0, false)) {
if (author.equals(rating.getAuthor())) {
return rating;
}
}
} catch (XWikiException e) {
return null;
}
return null;
}
@Override
public Rating getRating(String ratingId) throws RatingsException
{
try {
int i1 = ratingId.indexOf(".");
if (i1 == -1) {
throw new RatingsException(RatingsException.MODULE_PLUGIN_RATINGS,
RatingsException.ERROR_RATINGS_INVALID_RATING_ID, "Invalid rating ID, cannot parse rating id");
}
XWikiDocument doc = getXWiki().getDocument(ratingId, getXWikiContext());
if (doc.isNew()) {
throw new RatingsException(RatingsException.MODULE_PLUGIN_RATINGS,
RatingsException.ERROR_RATINGS_INVALID_RATING_ID, "Invalid rating ID, rating does not exist");
}
BaseObject object = doc.getObject(getRatingsClassName());
if (object == null) {
throw new RatingsException(RatingsException.MODULE_PLUGIN_RATINGS,
RatingsException.ERROR_RATINGS_INVALID_RATING_ID, "Invalid rating ID, rating does not exist");
}
String parentDocName = object.getStringValue(RATING_CLASS_FIELDNAME_PARENT);
XWikiDocument parentDoc = getXWikiContext().getWiki().getDocument(parentDocName, getXWikiContext());
return new SeparatePageRating(parentDoc.getDocumentReference(), doc, getXWikiContext(), this);
} catch (XWikiException e) {
throw new RatingsException(e);
}
}
/**
* Gets a SeparatePageRating instance from a document
*
* @param documentRef the reference of the document which the ratings are for
* @param doc the document which the ratings are for
* @return a SeparatePageRating
* @throws RatingsException when an error occurs while fetching the rating
*/
public Rating getRatingFromDocument(DocumentReference documentRef, XWikiDocument doc) throws RatingsException
{
return new SeparatePageRating(documentRef, doc, getXWikiContext(), this);
}
}