org.opentestsystem.delivery.testadmin.domain.Proctor.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.delivery.testadmin.domain.Proctor.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.testadmin.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.opentestsystem.delivery.testadmin.domain.Affinity.AffinityRule;
import org.opentestsystem.delivery.testadmin.domain.Affinity.AffinityType;
import org.opentestsystem.delivery.testadmin.domain.constraints.DuplicateAvailabilityWindow;
import org.opentestsystem.delivery.testadmin.domain.constraints.OverlappingAvailabilityWindow;
import org.opentestsystem.delivery.testadmin.domain.constraints.ValidEndTime;
import org.opentestsystem.delivery.testreg.domain.User;
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.mapping.Document;
import org.springframework.util.CollectionUtils;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;

@Document
@JsonIgnoreProperties(ignoreUnknown = true, value = { "dateWindows" })
@CompoundIndexes(value = { @CompoundIndex(name = "userMongoId", def = "{'user._id':1}", unique = true) })
@DuplicateAvailabilityWindow(message = "{timeperiod.duplicate.invalid}", node = "availabilityWindow.startDateTime")
@OverlappingAvailabilityWindow(message = "{timeperiod.overlap.invalid}", node = "availabilityWindow.startDateTime")
public class Proctor implements TestAdminBase, DateWindowable {

    private static final long serialVersionUID = 1830323774952289118L;

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

    @Id
    private String id;

    @Valid
    private List<Affinity> affinities;

    @Valid
    private List<AvailabilityWindow> availabilityWindow;

    private User user;

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

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

    public void setAvailabilityWindow(final List<AvailabilityWindow> availabilityWindows) {
        this.availabilityWindow = availabilityWindows;
    }

    public void addTimePeriods(final List<AvailabilityWindow> availabilityWindows) {
        if (getAvailabilityWindow() == null || getAvailabilityWindow().isEmpty()) {
            setAvailabilityWindow(new ArrayList<AvailabilityWindow>());
        }
        getAvailabilityWindow().addAll(availabilityWindows);
    }

    public List<AvailabilityWindow> getAvailabilityWindow() {
        return this.availabilityWindow;
    }

    @ValidEndTime
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class AvailabilityWindow implements Serializable, DateWindow {

        private static final long serialVersionUID = 8156730549695535082L;

        @NotNull(message = "{timeperiod.starttime.required}")
        private DateTime startDateTime;

        @NotNull(message = "{timeperiod.endtime.required}")
        private DateTime endDateTime;

        @NotNull(message = "{timeperiod.availability.empty}")
        private Availability availability;

        public AvailabilityWindow() {
            this(null, null, null);
        }

        public AvailabilityWindow(final DateTime startTime, final DateTime endTime,
                final Availability availability) {
            this.startDateTime = startTime;
            this.endDateTime = endTime;
            this.availability = availability;
        }

        @Override
        public DateTime getStartDateTime() {
            return this.startDateTime;
        }

        @JsonDeserialize(using = TZBasedDateTimeDeserialier.class)
        public void setStartDateTime(final DateTime startTime) {
            this.startDateTime = startTime;
        }

        @Override
        public DateTime getEndDateTime() {
            return this.endDateTime;
        }

        @JsonDeserialize(using = TZBasedDateTimeDeserialier.class)
        public void setEndDateTime(final DateTime endTime) {
            this.endDateTime = endTime;
        }

        public Availability getAvailability() {
            return this.availability;
        }

        public void setAvailability(final Availability availability) {
            this.availability = availability;
        }

        @Override
        public boolean equals(final Object obj) {
            if (obj instanceof AvailabilityWindow) {
                final DateTime startDateTime = ((AvailabilityWindow) obj).getStartDateTime();
                final DateTime endDateTime = ((AvailabilityWindow) obj).getEndDateTime();
                return startDateTime.isEqual(getStartDateTime()) && endDateTime.isEqual(getEndDateTime());
            }
            return false;
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(getStartDateTime(), getEndDateTime());
        }
    }

    public List<Affinity> getAffinities() {
        return this.affinities;
    }

    public void setAffinities(final List<Affinity> affinities) {
        this.affinities = affinities;
    }

    public User getUser() {
        return this.user;
    }

    public void setUser(final User user) {
        this.user = user;
    }

    public boolean hasSubjectAffinity() {
        if (hasAffinities()) {
            for (final Affinity affinity : this.affinities) {
                if (affinity.getType() == AffinityType.SUBJECT) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean hasGradeAffinity() {
        if (hasAffinities()) {
            for (final Affinity affinity : this.affinities) {
                if (affinity.getType() == AffinityType.GRADE) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean hasAssessmentAffinity() {
        if (hasAffinities()) {
            for (final Affinity affinity : this.affinities) {
                if (affinity.getType() == AffinityType.ASSESSMENT) {
                    return true;
                }
            }
        }
        return false;
    }

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

    public boolean isAvailableForTimeSlot(final TimeSlot timeSlot) {

        // if the user has not setup any availability windows just return true so the proctor can be scheduled
        if (this.availabilityWindow == null || this.availabilityWindow.isEmpty()) {
            return true;
        }

        final Interval timeSlotInterval = new Interval(timeSlot.getStartTime(), timeSlot.getEndTime());

        boolean passesAvailable = false;
        boolean passesUnavailable = true;

        for (final AvailabilityWindow window : this.availabilityWindow) {
            if (!passesAvailable || passesUnavailable) {
                final Interval windowInterval = new Interval(window.getStartDateTime(), window.getEndDateTime());

                if (Availability.AVAILABLE == window.getAvailability()) {

                    if (windowInterval.contains(timeSlotInterval)) {
                        passesAvailable = true;
                    }

                } else if (Availability.NOTAVAILABLE == window.getAvailability()) {

                    if (windowInterval.contains(timeSlotInterval) || windowInterval.overlaps(timeSlotInterval)) {
                        passesUnavailable = false;
                    }
                }
            }
        }

        return passesAvailable && passesUnavailable;
    }

    public boolean hasStrictAffinity() {
        for (final Affinity affinity : this.affinities) {
            if (affinity.getRule() == AffinityRule.STRICT) {
                return true;
            }
        }
        return false;
    }

    public Affinity findFirstStrictAffinity() {
        for (final Affinity affinity : this.affinities) {
            if (affinity.getRule() == AffinityRule.STRICT) {
                return affinity;
            }
        }
        return null;
    }

    public boolean hasAffinities() {
        return !CollectionUtils.isEmpty(this.affinities);
    }

    @Override
    public List<DateWindow> getDateWindows() {
        final List<DateWindow> dateWindows = Lists.newArrayList();
        if (getAvailabilityWindow() == null) {
            return dateWindows;
        }

        for (final AvailabilityWindow availabilityWindow : getAvailabilityWindow()) {
            dateWindows.add(availabilityWindow);
        }
        return dateWindows;
    }

}