package sis.studentinfo;
import java.io.Serializable;
import java.util.*;
import java.util.logging.Logger;
import sis.customize.exception.StudentNameFormatException;
import sis.studentinfo.strategy.BasicGradingStrategy;
import sis.studentinfo.strategy.GradingStrategy;
/**
* @author Carl Adler(C.A.)
* */
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
final static Logger logger = Logger.getLogger(Student.class.getName());
final static int CREDITS_REQUIRED_FOR_FULL_TIME = 12;
final static int MAX_NAME_PARTS = 3;
final static String IN_STATE = "CO";
final static String TOO_MANY_NAME_PARTS_MSG = "Student name '%s' contains more than %d parts";
private String name;
private String firstName = "";
private String middleName = "";
private String lastName;
private int credits;
private String state = "";
private String id;
private List<Grade> grades = new ArrayList<Grade>();
private List<Integer> charges = new ArrayList<Integer>();
private GradingStrategy gradingStrategy = new BasicGradingStrategy();
private int settings = 0x0;
public enum Grade {
A(4), B(3), C(2), D(1), F(0);
private int points;
Grade(int points) {
this.points = points;
}
public int getPoints() {
return points;
}
};
public enum Flag {
ON_CAMPUS(1), TAX_EXEMPT(2),
MINOR(4), TROUBLEMAKER(8);
private int mask;
Flag(int mask) {
this.mask = mask;
}
}
public Student(final String fullName) {
this.name = fullName;
credits = 0;
List<String> nameParts = split(fullName);
final int maximunNumberOfNameParts = 3;
if(nameParts.size() > maximunNumberOfNameParts){
String message = String.format(TOO_MANY_NAME_PARTS_MSG, fullName, MAX_NAME_PARTS);
Student.logger.info(message);
throw new StudentNameFormatException(message);
}
setName(nameParts);
}
private List<String> split(String fullName){
List<String> nameParts = new ArrayList<String>();
for(String part : fullName.split(" "))
nameParts.add(part);
return nameParts;
}
private void setName(List<String> nameParts){
this.lastName = removeLast(nameParts);
String name = removeLast(nameParts);
if(nameParts.isEmpty())
this.firstName = name;
else {
this.middleName = name;
this.firstName = removeLast(nameParts);
}
}
public String getName() {
return name;
}
public String getFirstName() {
return firstName;
}
public String getMiddleName() {
return middleName;
}
public String getLastName() {
return lastName;
}
private String removeLast(List<String> list){
if(list.isEmpty())
return " ";
return list.remove(list.size() - 1);
}
public void addCharge(int charge){
charges.add(charge);
}
public int totalCharges(){
int total = 0;
for (int charge : charges)
total += charge;
return total;
}
boolean isFullTime(){
return credits >= CREDITS_REQUIRED_FOR_FULL_TIME;
}
int getCredits(){
return credits;
}
void addCredits(int credits){
this.credits += credits;
}
void setState(String state){
this.state = state;
}
boolean isInState(){
return state.equalsIgnoreCase(IN_STATE);
}
void addGrade(Grade grade){
grades.add(grade);
}
void setGradingStrategy(GradingStrategy gradingStrategy) {
this.gradingStrategy = gradingStrategy;
}
double getGpa(){
Student.logger.fine("Begin getGpa " + System.currentTimeMillis());
if(grades.isEmpty())
return 0.0;
double total = 0.0;
for (Grade grade : grades)
total += gradingStrategy.getGradePointsFor(grade);
double result = total / grades.size();
Student.logger.fine("End getGpa " + System.currentTimeMillis());
return result;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void set(Flag... flags) {
for(Flag flag : flags)
settings |= flag.mask;
}
public void unset(Flag... flags) {
for(Flag flag : flags)
settings &= ~flag.mask;
}
public boolean isOn(Flag flag) {
return (settings & flag.mask) == flag.mask;
}
public boolean isOff(Flag flag) {
return !isOn(flag);
}
public static Student findByLastName(String lastName) {
return new Student(lastName);
}
}