org.opentestsystem.delivery.testreg.domain.Student.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.delivery.testreg.domain.Student.java

Source

/*
Educational Online Test Delivery System Copyright (c) 2013 American Institutes for Research
    
Distributed under the AIR Open Source License, Version 1.0 See accompanying file AIR-License-1_0.txt or at
http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf
 */

package org.opentestsystem.delivery.testreg.domain;

import static org.apache.commons.lang.StringUtils.isNotEmpty;
import static org.apache.commons.lang.StringUtils.isNumeric;
import static org.apache.commons.lang.StringUtils.trim;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.Valid;
import javax.validation.constraints.Size;

import com.fasterxml.jackson.annotation.JsonFormat;
import org.hibernate.validator.constraints.NotBlank;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.opentestsystem.delivery.testreg.domain.constraints.Alpha;
import org.opentestsystem.delivery.testreg.domain.constraints.Alphanumeric;
import org.opentestsystem.delivery.testreg.domain.constraints.Ascii;
import org.opentestsystem.delivery.testreg.domain.constraints.BirthDateFormat;
import org.opentestsystem.delivery.testreg.domain.constraints.DateFormat;
import org.opentestsystem.delivery.testreg.domain.constraints.LanguageCode;
import org.opentestsystem.delivery.testreg.domain.constraints.StudentEntryDate;
import org.opentestsystem.delivery.testreg.domain.constraints.StudentOrigin;
import org.opentestsystem.delivery.testreg.domain.constraints.ValidEnumType;
import org.opentestsystem.delivery.testreg.domain.constraints.ValidStateCode;
import org.opentestsystem.delivery.testreg.domain.search.StudentSearchRequest;
import org.opentestsystem.shared.search.domain.AbstractSearchRequest;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.base.Objects;
import com.google.common.collect.ObjectArrays;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamOmitField;

/**
 * The StudentIdentifier in Student class is being used as an entityId.
 */
@SuppressWarnings({ "PMD.ShortVariable" })
@Document
@JsonIgnoreProperties(ignoreUnknown = true)
@CompoundIndexes(value = {
        @CompoundIndex(name = "idAndState", def = "{'entityId':1, 'stateAbbreviation':1}", unique = true),
        @CompoundIndex(name = "externalSsidAndState", def = "{'externalSsid':1, 'stateAbbreviation':1, 'entityId':1}", unique = true) })
@StudentOrigin
@StudentEntryDate
@XStreamAlias("Student")
@XmlNotNull({ "stateAbbreviation", "lastName", "firstName", "birthDate", "entityId", "externalSsid",
        "gradeLevelWhenAssessed", "gender", "migrantStatus", "title3ProgramType" })
// Based on Validations, UI and Student Package Schema
@XmlOrderSequence({ "stateAbbreviation", "districtIdentifier", "institutionIdentifier", "lastName", "firstName",
        "middleName", "birthDate", "entityId", "externalSsid", "gradeLevelWhenAssessed", "gender",
        "hispanicOrLatino", "americanIndianOrAlaskaNative", "asian", "blackOrAfricanAmerican", "white",
        "nativeHawaiianOrPacificIsland", "twoOrMoreRaces", "iDEAIndicator", "lepStatus", "section504Status",
        "disadvantageStatus", "languageCode", "title3ProgressStatus", "migrantStatus", "firstEntryDateIntoUsSchool",
        "lepEntryDate", "lepExitDate", "title3ProgramType", "primaryDisabilityType", })
public class Student implements Sb11NonEntity, MultiRowExportable, Serializable {

    private static final long serialVersionUID = -8120474136096618225L;

    private static final String GET_RESOURCE_NAME = "/student/";

    public static final FormatType FORMAT_TYPE = FormatType.STUDENT;

    private static final String DATE_FORMAT = "yyyy-MM-dd";

    @Id
    @XStreamOmitField
    private String id;

    @Indexed
    @NotBlank(message = "{stateabbreviation.blank}")
    @ValidStateCode
    @FieldLabel("StateAbbreviation")
    @XStreamOmitField
    private String stateAbbreviation;

    @Indexed
    @NotBlank(message = "{student.studentId.blank}")
    @Alphanumeric(message = "{student.studentId.alphanumeric}")
    @Size(max = 40, message = "{student.studentId.size.max}")
    @FieldLabel("StudentIdentifier")
    @XStreamAlias("StudentIdentifier")
    private String entityId;

    @Indexed
    @NotBlank(message = "{student.institutionidentifier.blank}")
    @Alphanumeric(message = "{student.institutionidentifier.alphanumeric}")
    @Size(max = 40, message = "{student.institutionidentifier.size.max}")
    @FieldLabel("ResponsibleInstitutionIdentifier")
    @XStreamOmitField
    private String institutionIdentifier;

    @XStreamOmitField
    @Indexed
    private String institutionEntityMongoId;

    @Indexed
    @Alphanumeric(message = "{student.districtidentifier.alphanumeric}")
    @Size(max = 40, message = "{student.districtidentifier.size.max}")
    @FieldLabel("ResponsibleDistrictIdentifier")
    @XStreamOmitField
    private String districtIdentifier;

    @XStreamOmitField
    private String districtEntityMongoId;

    @Indexed
    @Ascii(isExtended = true, message = "{student.firstname.alphanumeric}")
    @Size(min = 0, max = 35, message = "{student.firstname.size.max}")
    @FieldLabel("FirstName")
    @XStreamAlias("FirstName")
    private String firstName;

    @Indexed
    @Ascii(isExtended = true, message = "{student.lastname.alphanumeric}")
    @Size(min = 0, max = 100, message = "{student.lastname.size.max}")
    @FieldLabel("LastOrSurname")
    @XStreamAlias("LastOrSurname")
    private String lastName;

    @Ascii(isExtended = true, message = "{student.middlename.alphanumeric}")
    @Size(min = 0, max = 35, message = "{student.middlename.size.max}")
    @FieldLabel("MiddleName")
    @XStreamAlias("MiddleName")
    private String middleName;

    @BirthDateFormat(datePattern = DATE_FORMAT, message = "{student.birthdate.format}")
    @FieldLabel("Birthdate")
    @XStreamAlias("Birthdate")
    private String birthDate;

    @Indexed
    @NotBlank(message = "{student.externalssid.blank}")
    @Alphanumeric(message = "{student.externalssid.alphanumeric}")
    @Size(max = 50, message = "{student.externalssid.size.max}")
    @FieldLabel("ExternalSSID")
    @XStreamAlias("AlternateSSID")
    private String externalSsid;

    @NotBlank(message = "{student.entrygradelevel.blank}")
    @ValidEnumType(types = { "IT", "PR", "PK", "TK", "KG", "01", "02", "03", "04", "05", "06", "07", "08", "09",
            "10", "11", "12", "13", "PS", "UG" }, message = "{student.entrygradelevel.type}")
    @FieldLabel("GradeLevelWhenAssessed")
    @XStreamAlias("GradeLevelWhenAssessed")
    private String gradeLevelWhenAssessed;

    @NotBlank(message = "{student.sex.blank}")
    @ValidEnumType(types = { "MALE", "FEMALE" }, casesensitive = false, message = "{student.sex.options}")
    @FieldLabel("Sex")
    @XStreamAlias("Sex")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            Gender.class }, strings = { "TITLECASE" })
    private String gender;

    @NotBlank(message = "{student.hispanicorlatino.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.hispanicorlatino.option}")
    @FieldLabel("HispanicOrLatinoEthnicity")
    @XStreamAlias("HispanicOrLatinoEthnicity")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String hispanicOrLatino;

    @NotBlank(message = "{student.americanindianoralaskanative.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.americanindianoralaskanative.option}")
    @FieldLabel("AmericanIndianOrAlaskaNative")
    @XStreamAlias("AmericanIndianOrAlaskaNative")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String americanIndianOrAlaskaNative;

    @NotBlank(message = "{student.asian.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.asian.option}")
    @FieldLabel("Asian")
    @XStreamAlias("Asian")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String asian;

    @NotBlank(message = "{student.blackorafricanamerican.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.blackorafricanamerican.option}")
    @FieldLabel("BlackOrAfricanAmerican")
    @XStreamAlias("BlackOrAfricanAmerican")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String blackOrAfricanAmerican;

    @NotBlank(message = "{student.white.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.white.option}")
    @FieldLabel("White")
    @XStreamAlias("White")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String white;

    @NotBlank(message = "{student.nativehawaiianorpacificisland.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.nativehawaiianorpacificisland.option}")
    @FieldLabel("NativeHawaiianOrOtherPacificIslander")
    @XStreamAlias("NativeHawaiianOrOtherPacificIslander")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String nativeHawaiianOrPacificIsland;

    @NotBlank(message = "{student.demographicracetwoormoreraces.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.demographicracetwoormoreraces.option}")
    @FieldLabel("DemographicRaceTwoOrMoreRaces")
    @XStreamAlias("DemographicRaceTwoOrMoreRaces")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String twoOrMoreRaces;

    @NotBlank(message = "{student.ideaindicator.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.ideaindicator.option}")
    @FieldLabel("IDEAIndicator")
    @XStreamAlias("IDEAIndicator")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String iDEAIndicator;

    @NotBlank(message = "{student.lepstatus.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.lepstatus.option}")
    @FieldLabel("LEPStatus")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    @XStreamAlias("LEPStatus")
    private String lepStatus;

    @NotBlank(message = "{student.section504status.blank}")
    @ValidEnumType(types = { "YES", "NO", "UNKNOWN/CANNOT PROVIDE" }, message = "{student.section504status.option}")
    @FieldLabel("Section504Status")
    @XStreamAlias("Section504Status")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            Section504Status.class }, strings = { "UPPERCASE", "TITLECASE" })
    private String section504Status;

    @NotBlank(message = "{student.disadvantagestatus.blank}")
    @ValidEnumType(types = { "YES", "NO" }, message = "{student.disadvantagestatus.option}")
    @FieldLabel("EconomicDisadvantageStatus")
    @XStreamAlias("EconomicDisadvantageStatus")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE" })
    private String disadvantageStatus;

    @LanguageCode(message = "{student.languagecode.invalid}")
    @FieldLabel("LanguageCode")
    @XStreamAlias("LanguageCode")
    private String languageCode; // listed as an enum, values should be at: http://ceds.ed.gov/languageCodes.aspx

    @Ascii(message = "{student.title3progress.option}")
    @FieldLabel("EnglishLanguageProficiencyLevel")
    @XStreamAlias("EnglishLanguageProficiencyLevel")
    private String title3ProgressStatus;

    @ValidEnumType(types = { "YES", "NO" }, message = "{student.migrantstatus.option}")
    @FieldLabel("MigrantStatus")
    @XStreamAlias("MigrantStatus")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            YesNoBoolean.class }, strings = { "TITLECASE_HANDLE_NULL_EMPTY" })
    private String migrantStatus;

    @DateFormat(datePattern = DATE_FORMAT, message = "{student.schoolfirstdate.format}")
    @FieldLabel("FirstEntryDateIntoUSSchool")
    @XStreamAlias("FirstEntryDateIntoUSSchool")
    private String firstEntryDateIntoUsSchool; // format YYYY-MM-DD

    @DateFormat(datePattern = DATE_FORMAT, message = "{student.lepentrydate.format}")
    @FieldLabel("LimitedEnglishProficiencyEntryDate")
    @XStreamAlias("LimitedEnglishProficiencyEntryDate")
    private String lepEntryDate; // format YYYY-MM-DD

    @DateFormat(datePattern = DATE_FORMAT, message = "{student.lepexitdate.format}")
    @FieldLabel("LEPExitDate")
    @XStreamAlias("LEPExitDate")
    private String lepExitDate; // format YYYY-MM-DD

    @ValidEnumType(types = { "DUALLANGUAGE", "TWOWAYIMMERSION", "TRANSITIONALBILINGUAL", "DEVELOPMENTALBILINGUAL",
            "HERITAGELANGUAGE", "SHELTEREDENGLISHINSTRUCTION", "STRUCTUREDENGLISHIMMERSION", "SDAIE",
            "CONTENTBASEDESL", "PULLOUTESL", "OTHER" }, message = "{student.title3ProgramType.option}")
    @FieldLabel("TitleIIILanguageInstructionProgramType")
    @XStreamAlias("TitleIIILanguageInstructionProgramType")
    @XStreamConverter(value = EnumBasedXStreamConverter.class, useImplicitType = false, types = {
            Title3ProgramType.class }, strings = { "UPPERCASE",
                    "TITLECASE_HANDLE_NULL_EMPTY" }, booleans = { false })
    private String title3ProgramType;

    @ValidEnumType(types = { "AUT", "DB", "DD", "EMN", "HI", "ID", "MD", "OI", "OHI", "SLD", "SLI", "TBI",
            "VI" }, message = "{student.primarydisabilitytype.format}")
    @FieldLabel("PrimaryDisabilityType")
    @XStreamAlias("PrimaryDisabilityType")
    private String primaryDisabilityType;

    @Valid
    private Object[] accommodations;

    @Alpha(message = "{delete.alpha}")
    @Size(max = 6, message = "{delete.size.max}")
    @FieldLabel("Delete")
    @XStreamOmitField
    private String delete;

    @FieldLabel("<Any of the Student Origin Fields>")
    @XStreamOmitField
    private final String race = ""; // Stub for Display. Not to be used anywhere

    @XStreamAsAttribute
    @XStreamAlias("StudentPackageVersion")
    private final Double studentPackageVersion = 2.0; // This is fixed for now. Not sure at this point if we need to increment
    // this.
    private boolean inValidAccommodationsSubject;

    public String getRace() {
        return this.race;
    }

    public enum Gender {
        Male, Female;
    }

    public enum YesNoBoolean {
        Yes, No
    }

    public enum Section504Status {
        YES("Yes"), NO("No"), UNKNOWN_CANNOTPROVIDE("Unknown/Cannot Provide");

        String desc;

        private Section504Status(final String inDescription) {
            this.desc = inDescription;
        }

        public static Section504Status getEnumByValue(final String value) {
            for (final Section504Status val : Section504Status.values()) {
                if (val.desc.equalsIgnoreCase(value)) {
                    return val;
                }
            }
            throw new IllegalArgumentException("Section504Status Not Found");
        }

        @Override
        public String toString() {
            return this.desc;
        }

    }

    public enum GradeLevel {

        INFANTTODDLER("IT"), PRESCHOOL("PR"), PREKINDERGARTEN("PK"), TRANSITIONALKINDERGARTEN("TK"), KINDERGARTEN(
                "KG"), FIRSTGRADE("01"), SECONDGRADE("02"), THIRDGRADE("03"), FOURTHGRADE("04"), FIFTHGRADE(
                        "05"), SIXTHGRADE("06"), SEVENTHGRADE("07"), EIGHTHGRADE("08"), NINTHGRADE(
                                "09"), TENTHGRADE("10"), ELEVENTHGRADE("11"), TWELFTHGRADE(
                                        "12"), GRADE13("13"), POSTSECONDARY("PS"), UNGRADED("UG");

        private final String grade;

        private GradeLevel(final String inGrade) {
            this.grade = inGrade;
        }

        public String getGrade() {
            return this.grade;
        }

        public static String padZeroIfNeeded(final String inGrade) {
            // Append leading '0' for grades between 1 and 9
            return isNotEmpty(inGrade) && isNumeric(inGrade) && Integer.parseInt(inGrade) < 10
                    ? "0" + Integer.parseInt(inGrade)
                    : inGrade;
        }

        public static GradeLevel fromGrade(final String inGrade) {
            final String zeroPaddedGrade = padZeroIfNeeded(inGrade);
            for (final GradeLevel level : values()) {

                if (zeroPaddedGrade.equalsIgnoreCase(level.getGrade())) {
                    return level;
                }
            }
            throw new IllegalArgumentException("Invalid GradeLevel");

        }

        /**
         * Alias for fromGrade to make things more consistent between all enums
         */
        public static GradeLevel getEnumByValue(final String value) {
            return fromGrade(value);
        }

        @Override
        @JsonValue
        public String toString() {
            return this.grade;
        }

    }

    public enum Title3ProgramType {
        DUALLANGUAGE("DualLanguage"), TWOWAYIMMERSION("TwoWayImmersion"), TRANSITIONALBILINGUAL(
                "TransitionalBilingual"), DEVELOPMENTALBILINGUAL("DevelopmentalBilingual"), HERITAGELANGUAGE(
                        "HeritageLanguage"), SHELTEREDENGLISHINSTRUCTION(
                                "ShelteredEnglishInstruction"), STRUCTUREDENGLISHIMMERSION(
                                        "StructuredEnglishImmersion"), SDAIE("SDAIE"), CONTENTBASEDESL(
                                                "ContentBasedESL"), PULLOUTESL("PullOutESL"), OTHER("Other");

        private String description;

        private Title3ProgramType(final String inDescription) {
            this.description = inDescription;
        }

        public String getDescription() {
            return this.description;
        }

        public void setDescription(final String description) {
            this.description = description;
        }

        @Override
        public String toString() {
            return this.description;
        }
    }

    public enum PrimaryDisabilityType {

        AUT("Autism"), DB("Deaf-blindness"), DD("Developmental delay"), EMN("Emotional disturbance"), HI(
                "Hearing impairment"), ID("Intellectual Disability"), MD(
                        "Multiple disabilities"), OI("Orthopedic impairment"), OHI("Other health impairment"), SLD(
                                "Specific learning disability"), SLI("Speech or language impairment"), TBI(
                                        "Traumatic brain injury"), VI("Visual impairment");

        private String description;

        private PrimaryDisabilityType(final String inDescription) {
            this.description = inDescription;
        }

        public String getDescription() {
            return this.description;
        }

        public void setDescription(final String description) {
            this.description = description;
        }
    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public void setId(final String inId) {
        this.id = inId;
    }

    public String getEntityId() {
        return this.entityId;
    }

    public void setEntityId(final String entityId) {
        this.entityId = entityId;
    }

    public String getStateAbbreviation() {
        return this.stateAbbreviation;
    }

    public void setStateAbbreviation(final String stateAbbreviation) {
        this.stateAbbreviation = stateAbbreviation;
    }

    public String getInstitutionIdentifier() {
        return this.institutionIdentifier;
    }

    public void setInstitutionIdentifier(final String institutionIdentifier) {
        this.institutionIdentifier = institutionIdentifier;
    }

    public String getDistrictIdentifier() {
        return this.districtIdentifier;
    }

    public void setDistrictIdentifier(final String districtIdentifier) {
        this.districtIdentifier = districtIdentifier;
    }

    public GradeLevel getGradeLevelWhenAssessed() {
        if (isNotEmpty(this.gradeLevelWhenAssessed)) {

            if (this.gradeLevelWhenAssessed.length() > 2) {// name is used
                return GradeLevel.valueOf(this.gradeLevelWhenAssessed);
            }
            return GradeLevel.fromGrade(this.gradeLevelWhenAssessed); // two character grade is used
        }
        throw new IllegalArgumentException("Invalid GradeLevel");
    }

    public String getGrade() {
        return this.gradeLevelWhenAssessed;
    }

    @JsonProperty
    public void setGradeLevelWhenAssessed(final String gradeLevelWhenAssessed) {
        if (isNotEmpty(gradeLevelWhenAssessed)) {
            try {
                this.gradeLevelWhenAssessed = GradeLevel.valueOf(gradeLevelWhenAssessed).grade;
            } catch (final IllegalArgumentException ex) {
                this.gradeLevelWhenAssessed = gradeLevelWhenAssessed;
                // Not required to rethrow
            }
        } else {
            this.gradeLevelWhenAssessed = gradeLevelWhenAssessed;
        }
    }

    public void setGradeLevelWhenAssessed(final GradeLevel gradeLevel) {
        if (gradeLevel != null) {
            this.gradeLevelWhenAssessed = gradeLevel.grade;
        }
    }

    public String getTwoOrMoreRaces() {
        return this.twoOrMoreRaces;
    }

    public void setTwoOrMoreRaces(final String twoOrMoreRaces) {
        if (isNotEmpty(twoOrMoreRaces)) {
            this.twoOrMoreRaces = twoOrMoreRaces.toUpperCase();
        } else {
            this.twoOrMoreRaces = twoOrMoreRaces;
        }
    }

    public String getiDEAIndicator() {
        return this.iDEAIndicator;
    }

    public void setiDEAIndicator(final String iDEAIndicator) {
        if (isNotEmpty(iDEAIndicator)) {
            this.iDEAIndicator = iDEAIndicator.toUpperCase();
        } else {
            this.iDEAIndicator = iDEAIndicator;
        }
    }

    public String getLepStatus() {
        return this.lepStatus;
    }

    public void setLepStatus(final String lepStatus) {
        if (isNotEmpty(lepStatus)) {
            this.lepStatus = lepStatus.toUpperCase();
        } else {
            this.lepStatus = lepStatus;
        }
    }

    public String getSection504Status() {
        return this.section504Status;

    }

    @JsonProperty
    public void setSection504Status(final String section504Status) {
        if (isNotEmpty(section504Status)) {
            this.section504Status = section504Status.toUpperCase();
        } else {
            this.section504Status = section504Status;
        }
    }

    public void setSection504Status(final Section504Status section504Status) {
        if (section504Status != null) {
            this.section504Status = section504Status.name();
        }
    }

    public void setHispanicOrLatino(final String hispanicOrLatino) {
        if (isNotEmpty(hispanicOrLatino)) {
            this.hispanicOrLatino = hispanicOrLatino.toUpperCase();
        } else {
            this.hispanicOrLatino = hispanicOrLatino;
        }
    }

    public void setAmericanIndianOrAlaskaNative(final String americanIndianOrAlaskaNative) {
        if (isNotEmpty(americanIndianOrAlaskaNative)) {
            this.americanIndianOrAlaskaNative = americanIndianOrAlaskaNative.toUpperCase();
        } else {
            this.americanIndianOrAlaskaNative = americanIndianOrAlaskaNative;
        }
    }

    public void setAsian(final String asian) {
        if (isNotEmpty(asian)) {
            this.asian = asian.toUpperCase();
        } else {
            this.asian = asian;
        }
    }

    public void setBlackOrAfricanAmerican(final String blackOrAfricanAmerican) {
        if (isNotEmpty(blackOrAfricanAmerican)) {
            this.blackOrAfricanAmerican = blackOrAfricanAmerican.toUpperCase();
        } else {
            this.blackOrAfricanAmerican = blackOrAfricanAmerican;
        }
    }

    public void setWhite(final String white) {
        if (isNotEmpty(white)) {
            this.white = white.toUpperCase();
        } else {
            this.white = white;
        }
    }

    public void setNativeHawaiianOrPacificIsland(final String nativeHawaiianOrPacificIsland) {
        if (isNotEmpty(nativeHawaiianOrPacificIsland)) {
            this.nativeHawaiianOrPacificIsland = nativeHawaiianOrPacificIsland.toUpperCase();
        } else {
            this.nativeHawaiianOrPacificIsland = nativeHawaiianOrPacificIsland;
        }
    }

    public String getTitle3ProgressStatus() {

        return this.title3ProgressStatus;
    }

    @JsonProperty
    public void setTitle3ProgressStatus(final String title3ProgressStatus) {
        this.title3ProgressStatus = title3ProgressStatus;

    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(final String inFirstName) {
        this.firstName = inFirstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(final String inLastName) {
        this.lastName = inLastName;
    }

    public String getMiddleName() {
        return this.middleName;
    }

    public void setMiddleName(final String inMiddleName) {
        this.middleName = inMiddleName;
    }

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    public DateTime getBirthDate() {
        return getDate(this.birthDate);

    }

    @JsonProperty
    public void setBirthDate(final String inBirthDate) {
        this.birthDate = inBirthDate;
    }

    public void setBirthDate(final DateTime inBirthDate) {
        if (inBirthDate != null) {
            this.birthDate = formatDate(inBirthDate);
        }
    }

    public String getExternalSsid() {
        return this.externalSsid;
    }

    public void setExternalSsid(final String inExternalSsid) {
        this.externalSsid = inExternalSsid;
    }

    public Gender getGender() {
        if (isNotEmpty(this.gender)) {
            return Gender.valueOf(this.gender);
        }
        throw new IllegalArgumentException("Invalid Gender");
    }

    @JsonProperty
    public void setGender(final String inGender) {

        if (isNotEmpty(inGender)) {
            this.gender = Character.toTitleCase(inGender.charAt(0)) + inGender.substring(1).toLowerCase();
        } else {

            this.gender = inGender;
        }
    }

    public void setGender(final Gender genderType) {
        if (genderType != null) {
            this.gender = genderType.name();
        }
    }

    public String getLanguageCode() {
        return this.languageCode;
    }

    public void setLanguageCode(final String inLanguageCode) {
        this.languageCode = inLanguageCode;
    }

    public String getMigrantStatus() {
        return this.migrantStatus;
    }

    public void setMigrantStatus(final String inMigrantStatus) {
        if (isNotEmpty(inMigrantStatus)) {
            this.migrantStatus = inMigrantStatus.toUpperCase();
        } else {
            this.migrantStatus = inMigrantStatus;
        }
    }

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    public DateTime getFirstEntryDateIntoUsSchool() {
        return getDate(this.firstEntryDateIntoUsSchool);
    }

    @JsonProperty
    public void setFirstEntryDateIntoUsSchool(final String inFirstEntryDateIntoUsSchool) {
        this.firstEntryDateIntoUsSchool = inFirstEntryDateIntoUsSchool;
    }

    public void setFirstEntryDateIntoUsSchool(final DateTime inFirstEntryDateIntoUsSchool) {
        if (inFirstEntryDateIntoUsSchool != null) {
            this.firstEntryDateIntoUsSchool = formatDate(inFirstEntryDateIntoUsSchool);
        }
    }

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    public DateTime getLepEntryDate() {
        return getDate(this.lepEntryDate);
    }

    @JsonProperty
    public void setLepEntryDate(final String inLepEntryDate) {
        this.lepEntryDate = inLepEntryDate;
    }

    public void setLepEntryDate(final DateTime inLepEntryDate) {
        if (inLepEntryDate != null) {
            this.lepEntryDate = formatDate(inLepEntryDate);
        }
    }

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    public DateTime getLepExitDate() {
        return getDate(this.lepExitDate);
    }

    public void setLepExitDate(final DateTime inLepExitDate) {
        if (inLepExitDate != null) {
            this.lepExitDate = formatDate(inLepExitDate);
        }
    }

    @JsonProperty
    public void setLepExitDate(final String inLepExitDate) {
        this.lepExitDate = inLepExitDate;
    }

    public Title3ProgramType getTitle3ProgramType() {
        if (isNotEmpty(this.title3ProgramType)) {
            return Title3ProgramType.valueOf(this.title3ProgramType);
        }
        return null;
    }

    @JsonProperty
    public void setTitle3ProgramType(final String title3Program) {
        if (isNotEmpty(title3Program)) {
            this.title3ProgramType = title3Program.toUpperCase();
        } else {
            this.title3ProgramType = title3Program;
        }
    }

    public void setTitle3ProgramType(final Title3ProgramType title3ProgramType) {
        if (title3ProgramType != null) {
            this.title3ProgramType = title3ProgramType.name();
        }
    }

    public PrimaryDisabilityType getPrimaryDisabilityType() {
        if (isNotEmpty(this.primaryDisabilityType)) {
            return PrimaryDisabilityType.valueOf(this.primaryDisabilityType);
        }
        return null;
    }

    public void setPrimaryDisabilityType(final PrimaryDisabilityType inPrimaryDisabilityType) {
        if (inPrimaryDisabilityType != null) {
            this.primaryDisabilityType = inPrimaryDisabilityType.name();
        }
    }

    @JsonProperty
    public void setPrimaryDisabilityType(final String inPrimaryDisabilityType) {
        if (isNotEmpty(inPrimaryDisabilityType)) {
            this.primaryDisabilityType = inPrimaryDisabilityType.toUpperCase();
        } else {
            this.primaryDisabilityType = inPrimaryDisabilityType;
        }
    }

    public String getDisadvantageStatus() {
        return this.disadvantageStatus;
    }

    public void setDisadvantageStatus(final String disadvantageStatus) {
        if (isNotEmpty(disadvantageStatus)) {
            this.disadvantageStatus = disadvantageStatus.toUpperCase();
        } else {
            this.disadvantageStatus = disadvantageStatus;
        }
    }

    public String getHispanicOrLatino() {
        return this.hispanicOrLatino;
    }

    public String getAmericanIndianOrAlaskaNative() {
        return this.americanIndianOrAlaskaNative;
    }

    public String getAsian() {
        return this.asian;
    }

    public String getBlackOrAfricanAmerican() {
        return this.blackOrAfricanAmerican;
    }

    public String getWhite() {
        return this.white;
    }

    public String getNativeHawaiianOrPacificIsland() {
        return this.nativeHawaiianOrPacificIsland;
    }

    public void setDelete(final String inDelete) {
        this.delete = trim(inDelete);
    }

    private DateTime getDate(final String strDate) {
        if (isNotEmpty(strDate)) {
            return DateTime.parse(strDate);
        }
        return null;
    }

    private String formatDate(final DateTime date) {
        final DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd");
        return fmt.print(date);

    }

    public Object[] getAccommodations() {
        return accommodations;
    }

    public void setAccommodations(Object[] accommodations) {
        this.accommodations = accommodations;
    }

    public String getInstitutionEntityMongoId() {
        return this.institutionEntityMongoId;
    }

    public void setInstitutionEntityMongoId(final String institutionEntityMongoId) {
        this.institutionEntityMongoId = institutionEntityMongoId;
    }

    public String getDistrictEntityMongoId() {
        return this.districtEntityMongoId;
    }

    public void setDistrictEntityMongoId(final String districtEntityMongoId) {
        this.districtEntityMongoId = districtEntityMongoId;
    }

    public static class Builder implements TestRegistrationBuilder<Student> {

        private final Object[] builderVals;

        public Builder(final Object... inVals) {
            this.builderVals = inVals;
        }

        @Override
        public Student build() {

            final Student builtObject = new Student();
            builtObject.setStateAbbreviation(
                    isNotEmpty((String) this.builderVals[DomainIndexConstants.STUDENT_STATE_ABBREVIATION_INDEX])
                            ? ((String) this.builderVals[DomainIndexConstants.STUDENT_STATE_ABBREVIATION_INDEX])
                                    .toUpperCase()
                            : "");
            builtObject.setDistrictIdentifier(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_DISTRICT_ID_INDEX]);
            builtObject.setInstitutionIdentifier(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_INSTITUTION_ID_INDEX]);
            builtObject.setLastName((String) this.builderVals[DomainIndexConstants.STUDENT_LASTNAME_INDEX]);
            builtObject.setFirstName((String) this.builderVals[DomainIndexConstants.STUDENT_FIRSTNAME_INDEX]);
            builtObject.setMiddleName((String) this.builderVals[DomainIndexConstants.STUDENT_MIDDLENAME_INDEX]);
            builtObject.setBirthDate((String) this.builderVals[DomainIndexConstants.STUDENT_BIRTHDAY_INDEX]);
            builtObject.setEntityId((String) this.builderVals[DomainIndexConstants.STUDENT_ENTITY_ID_INDEX]);
            builtObject
                    .setExternalSsid((String) this.builderVals[DomainIndexConstants.STUDENT_EXTERNAL_SSID_INDEX]);
            builtObject.setGradeLevelWhenAssessed(GradeLevel
                    .padZeroIfNeeded((String) this.builderVals[DomainIndexConstants.STUDENT_GRADE_INDEX]));
            builtObject.setGender((String) this.builderVals[DomainIndexConstants.STUDENT_GENDER_INDEX]);
            builtObject.setHispanicOrLatino(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_HISPANICORLATINO_INDEX]);
            builtObject.setAmericanIndianOrAlaskaNative(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_AMERICANINDIANORALASKANATIVE_INDEX]);
            builtObject.setAsian((String) this.builderVals[DomainIndexConstants.STUDENT_ASIAN_INDEX]);
            builtObject.setBlackOrAfricanAmerican(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_BLACKORAFRICANAMERICAN_INDEX]);
            builtObject.setWhite((String) this.builderVals[DomainIndexConstants.STUDENT_WHITE_INDEX]);
            builtObject.setNativeHawaiianOrPacificIsland(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_NATIVEHAWAIIANORPACIFICISLAND_INDEX]);
            builtObject.setTwoOrMoreRaces(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_TWOORMORERACES_INDEX]);
            builtObject
                    .setiDEAIndicator((String) this.builderVals[DomainIndexConstants.STUDENT_IDEAINDICATOR_INDEX]);
            builtObject.setLepStatus((String) this.builderVals[DomainIndexConstants.STUDENT_LEPSTATUS_INDEX]);
            builtObject.setSection504Status(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_SECTION504STATUS_INDEX]);
            builtObject.setDisadvantageStatus(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_DISADVANTAGESTATUS_INDEX]);
            builtObject.setLanguageCode((String) this.builderVals[DomainIndexConstants.STUDENT_LANGUAGECODE_INDEX]);
            builtObject.setTitle3ProgressStatus(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_TITLE3PROGRESSSTATUS_INDEX]);
            builtObject
                    .setMigrantStatus((String) this.builderVals[DomainIndexConstants.STUDENT_MIGRANTSTATUS_INDEX]);
            builtObject.setFirstEntryDateIntoUsSchool(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_FIRSTENTRYDATEINTOUSSCHOOL_INDEX]);
            builtObject.setLepEntryDate((String) this.builderVals[DomainIndexConstants.STUDENT_LEPENTRYDATE_INDEX]);
            builtObject.setLepExitDate((String) this.builderVals[DomainIndexConstants.STUDENT_LEPEXITDATE_INDEX]);
            builtObject.setTitle3ProgramType(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_TITLE3PROGRAMTYPE_INDEX]);
            builtObject.setPrimaryDisabilityType(
                    (String) this.builderVals[DomainIndexConstants.STUDENT_PRIMARYDISABILITYTYPE_INDEX]);
            builtObject.setDelete((String) this.builderVals[DomainIndexConstants.STUDENT_DELETE_INDEX]);
            builtObject.setAccommodations(new Object[] {}); // Make it empty

            return builtObject;
        }
    }

    @Override
    public Action getAction() {
        return "DELETE".equals(this.delete) ? Action.DEL : Action.UPD;
    }

    public String getDelete() {
        return this.delete;
    }

    @Override
    public FormatType getFormatType() {
        return FORMAT_TYPE;
    }

    @JsonProperty
    public String getUrl() {
        return GET_RESOURCE_NAME + this.id;
    }

    /**
     * Transform student record to String array which contains only student information
     * (no accommodation info - for that use toMultiRowStringArray).
     */
    @Override
    public String[] toStringArray() {
        final String[] elements = new String[30];
        elements[DomainIndexConstants.STUDENT_STATE_ABBREVIATION_INDEX] = this.stateAbbreviation;
        elements[DomainIndexConstants.STUDENT_DISTRICT_ID_INDEX] = this.districtIdentifier;
        elements[DomainIndexConstants.STUDENT_INSTITUTION_ID_INDEX] = this.institutionIdentifier;
        elements[DomainIndexConstants.STUDENT_LASTNAME_INDEX] = this.lastName;
        elements[DomainIndexConstants.STUDENT_FIRSTNAME_INDEX] = this.firstName;
        elements[DomainIndexConstants.STUDENT_MIDDLENAME_INDEX] = this.middleName;
        elements[DomainIndexConstants.STUDENT_BIRTHDAY_INDEX] = this.birthDate;
        elements[DomainIndexConstants.STUDENT_ENTITY_ID_INDEX] = this.entityId;
        elements[DomainIndexConstants.STUDENT_EXTERNAL_SSID_INDEX] = this.externalSsid;
        elements[DomainIndexConstants.STUDENT_GRADE_INDEX] = this.gradeLevelWhenAssessed;
        elements[DomainIndexConstants.STUDENT_GENDER_INDEX] = this.gender;
        elements[DomainIndexConstants.STUDENT_HISPANICORLATINO_INDEX] = this.hispanicOrLatino;
        elements[DomainIndexConstants.STUDENT_AMERICANINDIANORALASKANATIVE_INDEX] = this.americanIndianOrAlaskaNative;
        elements[DomainIndexConstants.STUDENT_ASIAN_INDEX] = this.asian;
        elements[DomainIndexConstants.STUDENT_BLACKORAFRICANAMERICAN_INDEX] = this.blackOrAfricanAmerican;
        elements[DomainIndexConstants.STUDENT_WHITE_INDEX] = this.white;
        elements[DomainIndexConstants.STUDENT_NATIVEHAWAIIANORPACIFICISLAND_INDEX] = this.nativeHawaiianOrPacificIsland;
        elements[DomainIndexConstants.STUDENT_TWOORMORERACES_INDEX] = this.twoOrMoreRaces;
        elements[DomainIndexConstants.STUDENT_IDEAINDICATOR_INDEX] = this.iDEAIndicator;
        elements[DomainIndexConstants.STUDENT_LEPSTATUS_INDEX] = this.lepStatus;
        elements[DomainIndexConstants.STUDENT_SECTION504STATUS_INDEX] = this.section504Status;
        elements[DomainIndexConstants.STUDENT_DISADVANTAGESTATUS_INDEX] = this.disadvantageStatus;
        elements[DomainIndexConstants.STUDENT_LANGUAGECODE_INDEX] = this.languageCode;
        elements[DomainIndexConstants.STUDENT_TITLE3PROGRESSSTATUS_INDEX] = this.title3ProgressStatus;
        elements[DomainIndexConstants.STUDENT_MIGRANTSTATUS_INDEX] = this.migrantStatus;
        elements[DomainIndexConstants.STUDENT_FIRSTENTRYDATEINTOUSSCHOOL_INDEX] = this.firstEntryDateIntoUsSchool;
        elements[DomainIndexConstants.STUDENT_LEPENTRYDATE_INDEX] = this.lepEntryDate;
        elements[DomainIndexConstants.STUDENT_LEPEXITDATE_INDEX] = this.lepExitDate;
        elements[DomainIndexConstants.STUDENT_TITLE3PROGRAMTYPE_INDEX] = this.title3ProgramType;
        elements[DomainIndexConstants.STUDENT_PRIMARYDISABILITYTYPE_INDEX] = this.primaryDisabilityType;
        return elements;
    }

    @Override
    public String getAlternateKey() {
        return new StringBuilder().append("entityId: ").append(this.entityId).append(", externalSsid: ")
                .append(this.externalSsid).append(", stateAbbreviation: ").append(this.stateAbbreviation)
                .toString();
    }

    @Override
    public AbstractSearchRequest createAlternateKeySearchRequest() {

        final Map<String, String[]> reqMap = new HashMap<String, String[]>();
        reqMap.put(StudentSearchRequest.SEARCH_KEY_ENTITY_ID_EXACT, new String[] { this.entityId });
        reqMap.put(StudentSearchRequest.SEARCH_KEY_STATE_ID, new String[] { this.stateAbbreviation });
        reqMap.put(StudentSearchRequest.SEARCH_KEY_EXTERNAL_SSID, new String[] { this.externalSsid });

        final StudentSearchRequest request = new StudentSearchRequest(reqMap);

        return request;
    }

    // equals and hashcode based upon alternate key (does not compare all properties)
    @Override
    public boolean equals(final Object obj) {
        if (obj instanceof Student) {
            final Student student = (Student) obj;
            return com.google.common.base.Objects.equal(this.entityId, student.getEntityId())
                    && com.google.common.base.Objects.equal(this.stateAbbreviation, student.getStateAbbreviation());
        }

        return false;
    }

    @Override
    public int hashCode() {
        return com.google.common.base.Objects.hashCode(this.entityId, this.stateAbbreviation);
    }

    /**
     * Returns {@code Accommodation} attached to the {@code Assessment}
     *
     * @param assessment
     *        Assessment for which the Accommodation is needed
     * @return Attached Accommodation
     */
    public Map<String, Object> getAccommodation(final String assessmentSubjectCode) {

        Object[] accommodations = this.getAccommodations();
        Map<String, Object> accReturn = null;
        int accSize = 0;
        if (accommodations != null) {
            accSize = accommodations.length;
            for (int i = 0; i < accSize; i++) {
                Object obj = accommodations[i];
                Map<String, Object> acc = (Map<String, Object>) obj;
                if (acc.get("subject") != null
                        && acc.get("subject").toString().equalsIgnoreCase(assessmentSubjectCode)) {

                    accReturn = acc;
                }
            }

        }
        return accReturn;
    }

    public boolean hasAccommodations() {
        if (this.accommodations != null) {
            return (this.accommodations.length > 0);
        }
        return false;
    }

    public boolean hasAccommodations(final Assessment assessment) {
        Object[] accommodations = this.getAccommodations();
        int accSize = 0;
        if (accommodations != null) {
            accSize = accommodations.length;
            for (int i = 0; i < accSize; i++) {
                Object obj = accommodations[i];
                Map<String, Object> acc = (Map<String, Object>) obj;
                if (acc.get("subject") != null
                        && acc.get("subject").toString().equalsIgnoreCase(assessment.getSubjectCode())) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean isInValidAccommodationsSubject() {
        return this.inValidAccommodationsSubject;
    }

    public void setInValidAccommodationsSubject(final boolean inValidAccommodationsSubject) {
        this.inValidAccommodationsSubject = inValidAccommodationsSubject;
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(getClass()).add("id", this.id).add("entityId", this.entityId)
                .add("stateAbbreviation", this.stateAbbreviation)
                .add("institutionIdentifier", this.institutionIdentifier)
                .add("institutionEntityMongoId", this.institutionEntityMongoId)
                .add("districtIdentifier", this.districtIdentifier)
                .add("districtEntityMongoId", this.districtEntityMongoId).add("firstName", this.firstName)
                .add("lastName", this.lastName).toString();

    }

    /**
     * Returns only accommodation information about a student.
     * Use toStringArray() to get actual student record information.
     */
    @SuppressWarnings("unchecked")
    @Override
    public String[][] toMultiRowStringArray() {
        String[][] rows;
        Object[] accommodations = this.getAccommodations();
        if (accommodations != null && accommodations.length > 0) {
            rows = new String[this.accommodations.length][toStringArray().length + getAccommodations().length];
            int rowCount = 0;
            int accSize = 0;
            accSize = accommodations.length;
            for (int i = 0; i < accSize; i++) {
                Object obj = accommodations[i];
                Map<String, Object> acc = (Map<String, Object>) obj;
                Set<String> accommodationNames = acc.keySet();
                List<String> accommo = new ArrayList<String>();
                for (String str : accommodationNames) {
                    if (!str.equalsIgnoreCase("studentId") && !str.equalsIgnoreCase("stateAbbreviation")
                            && !str.equalsIgnoreCase("_id")
                            && !str.equalsIgnoreCase("atleastOneAccommodationField")) {
                        if (acc.get(str).toString().contains("[")) {
                            List<String> multi = (List<String>) acc.get(str);
                            StringBuffer namesSB = new StringBuffer();
                            if (multi != null) {
                                for (String multiAccomo : multi) {
                                    namesSB.append(multiAccomo).append(";");
                                }
                            }
                            if (namesSB.toString().contains(";")) {
                                namesSB.replace(namesSB.length() - 1, namesSB.length(), "");
                            }
                            accommo.add(namesSB.toString());
                        } else {
                            accommo.add(acc.get(str).toString());
                        }
                    }
                }
                String[] tempAccommodations = new String[accommo.size()];
                tempAccommodations = accommo.toArray(tempAccommodations);
                rows[rowCount++] = ObjectArrays.concat(toStringArray(), tempAccommodations, String.class);
            }
        } else {
            rows = new String[1][toStringArray().length];
            rows[0] = toStringArray();
        }
        return rows;
    }
}