/********************************************************************************** * * $Id: GradableObject.java 105077 2012-02-24 22:54:29Z ottenhoff@longsight.com $ * *********************************************************************************** * * Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation, The MIT Corporation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.sakaiproject.tool.gradebook; import java.io.Serializable; import java.util.Comparator; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * A GradableObject is a component of a Gradebook for which students can be * assigned a GradeRecord. * * @author <a href="mailto:jholtzman@berkeley.edu">Josh Holtzman</a> */ public abstract class GradableObject implements Serializable { protected static final Log log = LogFactory.getLog(GradableObject.class); protected Long id; protected int version; protected Gradebook gradebook; protected String name; protected Integer sortOrder; protected Double mean; // not persisted; not used in all contexts (in Overview & Assignment Grading, // not in Roster or Student View) protected boolean removed; // We had trouble with foreign key constraints in the UCB pilot when // instructors "emptied" all scores for an assignment and then tried to // delete the assignment. Instead, we should hide the "removed" assignments // from the app by filtering the removed assignments in the hibernate queries public static Comparator<GradableObject> defaultComparator; public static Comparator<GradableObject> sortingComparator; public static Comparator<Assignment> dateComparator; public static Comparator<GradableObject> meanComparator; public static Comparator<GradableObject> nameComparator; public static Comparator<GradableObject> idComparator; public static Comparator<Assignment> categoryComparator; static { categoryComparator = new Comparator<Assignment>() { @SuppressWarnings("unchecked") public int compare(Assignment one, Assignment two) { if (one.getCategory() == null && two.getCategory() == null) { return 0; } else if (one.getCategory() == null) { return 1; // no cats to the end } else if (two.getCategory() == null) { return -1; // no cats to the end } else { // compare the category names the same way as the normal comparator return Category.nameComparator.compare(one.getCategory(), two.getCategory()); } } @Override public String toString() { return "GradableObject.categoryComparator"; } }; idComparator = new Comparator<GradableObject>() { public int compare(GradableObject one, GradableObject two) { if (one.getId() == null && two.getId() == null) { return 0; } else if (one.getName() == null) { return 1; } else if (two.getName() == null) { return -1; } else { return one.getId().compareTo(two.getId()); } } @Override public String toString() { return "GradableObject.idComparator"; } }; nameComparator = new Comparator<GradableObject>() { public int compare(GradableObject one, GradableObject two) { if (one.getName() == null && two.getName() == null) { return idComparator.compare(one, two); } else if (one.getName() == null) { return 1; } else if (two.getName() == null) { return -1; } else { return one.getName().toLowerCase().compareTo(two.getName().toLowerCase()); } } @Override public String toString() { return "GradableObject.nameComparator"; } }; meanComparator = new Comparator<GradableObject>() { public int compare(GradableObject one, GradableObject two) { if (one.getMean() == null && two.getMean() == null) { return nameComparator.compare(one, two); } else if (one.getMean() == null) { return 1; } else if (two.getMean() == null) { return -1; } else { return one.getMean().compareTo(two.getMean()); } } @Override public String toString() { return "GradableObject.meanComparator"; } }; dateComparator = new Comparator<Assignment>() { public int compare(Assignment one, Assignment two) { if (one.getDueDate() == null && two.getDueDate() == null) { return nameComparator.compare(one, two); } else if (one.getDueDate() == null) { return 1; } else if (two.getDueDate() == null) { return -1; } else { return one.getDueDate().compareTo(two.getDueDate()); } } @Override public String toString() { return "GradableObject.dateComparator"; } }; sortingComparator = new Comparator<GradableObject>() { public int compare(GradableObject one, GradableObject two) { if (one.getSortOrder() == null && two.getSortOrder() == null) { if (one.getClass().equals(two.getClass()) && one.getClass().isAssignableFrom(Assignment.class) ) { // special handling for assignments return dateComparator.compare((Assignment)one, (Assignment)two); } else { return nameComparator.compare(one, two); } } else if (one.getSortOrder() == null) { return 1; } else if (two.getSortOrder() == null) { return -1; } else { return one.getSortOrder().compareTo(two.getSortOrder()); } } @Override public String toString() { return "GradableObject.sortingComparator"; } }; defaultComparator = sortingComparator; } /** * @return Whether this gradable object is a course grade */ public abstract boolean isCourseGrade(); /** * @return Whether this gradable object is an assignment */ public abstract boolean isAssignment(); /** * @return Whether this gradable object is a category */ public abstract boolean getIsCategory(); /** * @return Returns the id. */ public Long getId() { return id; } /** * @param id The id to set. */ public void setId(Long id) { this.id = id; } /** * @return Returns the gradebook. */ public Gradebook getGradebook() { return gradebook; } /** * @param gradebook The gradebook to set. */ public void setGradebook(Gradebook gradebook) { this.gradebook = gradebook; } /** * @return Returns the mean. */ public Double getMean() { return mean; } /** * @return Returns the mean while protecting against displaying NaN. */ public Double getFormattedMean() { if(mean == null || mean.equals(Double.valueOf(Double.NaN))) { return null; } else { return Double.valueOf(mean.doubleValue() / 100.0); } } /** * @param mean The mean to set. */ public void setMean(Double mean) { this.mean = mean; } /** * This should really only be a field in Assignment objects, since * the string describing CourseGrade needs to allow for localization. * Unfortunately, such we keep CourseGrade and Assignment objects in * the same table, and since we want Assignment names to be enforced * as non-nullable, we're stuck with a bogus CourseGrade "name" field * for now. The UI will have to be smart enough to disregard it. * * @return Returns the name. */ public String getName() { return name; } /** * @param name The name to set. */ public void setName(String name) { this.name = name; } /** * @return Returns the version. */ public int getVersion() { return version; } /** * @param version The version to set. */ public void setVersion(int version) { this.version = version; } /** * @return Returns the removed. */ public boolean isRemoved() { return removed; } /** * @param removed The removed to set. */ public void setRemoved(boolean removed) { this.removed = removed; } public String toString() { return new ToStringBuilder(this) .append("id", id) .append("name", name) .append("sort", sortOrder) .toString(); } public boolean equals(Object other) { if (!(other instanceof GradableObject)) { return false; } GradableObject go = (GradableObject)other; return new EqualsBuilder() .append(gradebook, go.getGradebook()) .append(id, go.getId()) .append(name, go.getName()).isEquals(); } public int hashCode() { return new HashCodeBuilder() .append(gradebook) .append(id) .append(name) .toHashCode(); } private int sortTotalItems = 1; private int sortTruePosition = -1; public void assignSorting(int sortTotalItems, int sortTruePosition) { // this will help correctly figure out the first/last setting and sorting this.sortTotalItems = sortTotalItems; this.sortTruePosition = sortTruePosition; } public boolean isFirst() { return sortTruePosition == 0; } public boolean isLast() { return sortTruePosition >= (sortTotalItems - 1); } public int getSortPosition() { return sortTruePosition; } public Integer getSortOrder() { return sortOrder; } public void setSortOrder(Integer sortOrder) { this.sortOrder = sortOrder; } }