package org.karmaexchange.dao;
import static org.karmaexchange.util.UserService.getCurrentUserKey;
import java.util.Date;
import javax.annotation.Nullable;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.karmaexchange.resources.msg.ErrorResponseMsg;
import org.karmaexchange.resources.msg.ErrorResponseMsg.ErrorInfo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Index;
@XmlRootElement
@Entity
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper=true)
@ToString(callSuper=true)
public class Review extends NameBaseDao<Review> {
private Rating rating;
@Index
private Date commentCreationDate;
private String comment;
// At this point reviews will have no comments associated with them. Instead comments will
// be associate with events and organization comments on facebook.
public void initPreUpsert(Key<?> owner, Key<User> authorKey) {
if (name == null) {
name = authorKey.getString();
this.owner = owner;
}
}
@Override
protected void preProcessInsert() {
super.preProcessInsert();
updateCommentCreationDate(null);
validateReview();
}
@Override
protected void processUpdate(Review prevReview) {
super.processUpdate(prevReview);
updateCommentCreationDate(prevReview);
validateReview();
}
@Override
protected void processDelete() {
super.processDelete();
validateAuthorMatches();
}
private void updateCommentCreationDate(Review prevReview) {
if (comment == null) {
commentCreationDate = null;
} else {
if ((prevReview != null) && (prevReview.commentCreationDate != null)) {
// The user is just updating the comment so keep the previous comment creation date.
commentCreationDate = prevReview.commentCreationDate;
} else {
commentCreationDate = new Date();
}
}
}
private void validateReview() {
if (rating == null) {
throw ErrorResponseMsg.createException(
"a rating must be specified", ErrorInfo.Type.BAD_REQUEST);
}
validateAuthorMatches();
}
private void validateAuthorMatches() {
if (!getCurrentUserKey().equals(getAuthor())) {
throw ErrorResponseMsg.createException("reviews can only be mutated by the owner",
ErrorInfo.Type.BAD_REQUEST);
}
}
@XmlTransient
@Nullable
public Key<User> getAuthor() {
return (name == null) ? null : Key.<User>create(name);
}
@Override
protected Permission evalPermission() {
// TODO(avaliani): fill this in. Organizers of events should have
// the ability to delete pictures also if the picture is owned by an
// event.
if (getAuthor().equals(getCurrentUserKey())) {
return Permission.ALL;
} else {
return Permission.READ;
}
}
public static <T> Key<Review> getKeyForCurrentUser(T resource) {
return getKeyForCurrentUser(Key.create(resource));
}
public static Key<Review> getKeyForCurrentUser(Key<?> owner) {
return getKeyForUser(owner, getCurrentUserKey());
}
public static Key<Review> getKeyForUser(Key<?> owner, Key<User> authorKey) {
return Key.<Review>create(owner, Review.class, authorKey.getString());
}
}