package hirondelle.movies.edit;
import java.math.BigDecimal;
import java.util.*;
import hirondelle.movies.exception.InvalidInputException;
import hirondelle.movies.util.Util;
public final class Movie implements Comparable<Movie>{
Movie(
String aId, String aTitle, Date aDateViewed, BigDecimal aRating, String aComment
) throws InvalidInputException {
fId = aId;
fTitle = aTitle;
fDateViewed = aDateViewed;
fRating = aRating;
fComment = aComment;
validateState();
}
Movie(
String aId, String aTitle, String aDateViewed, String aRating, String aComment
) throws InvalidInputException {
this(
aId, aTitle, Util.parseDate(aDateViewed, "Date Viewed"),
Util.parseBigDecimal(aRating, "Rating"), aComment
);
}
String getId(){ return fId; }
void setId(String aId){ fId = aId; }
String getTitle(){ return fTitle; }
Date getDateViewed(){ return fDateViewed; }
BigDecimal getRating(){ return fRating; }
String getComment(){ return fComment; }
@Override public boolean equals(Object aThat){
if ( this == aThat ) return true;
if ( !(aThat instanceof Movie) ) return false;
Movie that = (Movie)aThat;
return
areEqual(this.fTitle, that.fTitle) &&
areEqual(this.fDateViewed, that.fDateViewed) &&
areEqual(this.fRating, that.fRating) &&
areEqual(this.fComment, that.fComment)
;
}
@Override public int hashCode(){
int result = 17;
result = addHash(result, fTitle);
result = addHash(result, fDateViewed);
result = addHash(result, fRating);
result = addHash(result, fComment);
return result;
}
@Override public String toString(){
return
"Movie Id:" + fId + " Title:" + fTitle + " Date Viewed:" + fDateViewed +
" Rating:" + fRating + " Comment: " + fComment
;
}
@Override public int compareTo(Movie aThat) {
if ( this == aThat ) return EQUAL;
int comparison = DESCENDING*comparePossiblyNull(this.fDateViewed, aThat.fDateViewed);
if ( comparison != EQUAL ) return comparison;
comparison = this.fTitle.compareTo(aThat.fTitle);
if ( comparison != EQUAL ) return comparison;
comparison = comparePossiblyNull(this.fRating, aThat.fRating);
if ( comparison != EQUAL ) return comparison;
comparison = comparePossiblyNull(this.fComment, aThat.fComment);
if ( comparison != EQUAL ) return comparison;
return EQUAL;
}
public static Comparator<Movie> TITLE_SORT = new Comparator<Movie>(){
@Override public int compare(Movie aThis, Movie aThat) {
if ( aThis == aThat ) return EQUAL;
int comparison = aThis.fTitle.compareTo(aThat.fTitle);
if ( comparison != EQUAL ) return comparison;
comparison = DESCENDING*comparePossiblyNull(aThis.fDateViewed, aThat.fDateViewed);
if ( comparison != EQUAL ) return comparison;
comparison = comparePossiblyNull(aThis.fRating, aThat.fRating);
if ( comparison != EQUAL ) return comparison;
comparison = comparePossiblyNull(aThis.fComment, aThat.fComment);
if ( comparison != EQUAL ) return comparison;
return EQUAL;
};
};
public static Comparator<Movie> RATING_SORT = new Comparator<Movie>(){
@Override public int compare(Movie aThis, Movie aThat) {
if ( aThis == aThat ) return EQUAL;
int comparison = DESCENDING*comparePossiblyNull(aThis.fRating, aThat.fRating);
if ( comparison != EQUAL ) return comparison;
comparison = DESCENDING*comparePossiblyNull(aThis.fDateViewed, aThat.fDateViewed);
if ( comparison != EQUAL ) return comparison;
comparison = aThis.fTitle.compareTo(aThat.fTitle);
if ( comparison != EQUAL ) return comparison;
comparison = comparePossiblyNull(aThis.fComment, aThat.fComment);
if ( comparison != EQUAL ) return comparison;
return EQUAL;
};
};
public static Comparator<Movie> COMMENT_SORT = new Comparator<Movie>(){
@Override public int compare(Movie aThis, Movie aThat) {
if ( aThis == aThat ) return EQUAL;
int comparison = comparePossiblyNull(aThis.fComment, aThat.fComment);
if ( comparison != EQUAL ) return comparison;
comparison = aThis.fTitle.compareTo(aThat.fTitle);
if ( comparison != EQUAL ) return comparison;
comparison = comparePossiblyNull(aThis.fRating, aThat.fRating);
if ( comparison != EQUAL ) return comparison;
comparison = DESCENDING*comparePossiblyNull(aThis.fDateViewed, aThat.fDateViewed);
if ( comparison != EQUAL ) return comparison;
return EQUAL;
};
};
private String fId;
private final String fTitle;
private final Date fDateViewed;
private final BigDecimal fRating;
private final String fComment;
private static final BigDecimal TEN = new BigDecimal("10.0");
private static final int EQUAL = 0;
private static final int DESCENDING = -1;
private void validateState() throws InvalidInputException {
InvalidInputException ex = new InvalidInputException();
if( ! Util.textHasContent(fTitle) ) {
ex.add("Title must have content");
}
if ( fRating != null ){
if ( fRating.compareTo(BigDecimal.ZERO) < 0 ) {
ex.add("Rating cannot be less than 0.");
}
if ( fRating.compareTo(TEN) > 0 ) {
ex.add("Rating cannot be greater than 10.");
}
}
if ( ex.hasErrors() ) {
throw ex;
}
}
private boolean areEqual(Object aThis, Object aThat){
return aThis == null ? aThat == null : aThis.equals(aThat);
}
private int addHash(int aHash, Object aField){
int result = 37*aHash;
if (aField != null){
result = result + aField.hashCode();
}
return result;
}
private static <T extends Comparable<T>> int comparePossiblyNull(T aThis, T aThat){
int result = EQUAL;
int BEFORE = -1;
int AFTER = 1;
if(aThis != null && aThat != null){
result = aThis.compareTo(aThat);
}
else {
if(aThis == null && aThat == null) {
}
else if(aThis == null && aThat != null) {
result = BEFORE;
}
else if( aThis != null && aThat == null) {
result = AFTER;
}
}
return result;
}
}