package elw.dao.ctx; import elw.vo.Course; import elw.vo.Enrollment; import elw.vo.Group; import elw.vo.Student; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Days; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.util.Iterator; import java.util.Map; import java.util.TimeZone; /** * Parameter Object for general Enrollment Context. */ public class CtxEnrollment { public static final DateTimeFormatter FMT_DATE_TIME_NICE = DateTimeFormat.forPattern("EEE MMM dd HH:mm"); public final Enrollment enr; public final Group group; public final Course course; public final Iterable<CtxStudent> students; public CtxEnrollment( final Enrollment enr, final Course course, final Group group ) { this.group = group; this.course = course; this.enr = enr; this.students = new Iterable<CtxStudent>() { public Iterator<CtxStudent> iterator() { final Iterator<Map.Entry<String, Student>> studentIterator = group.getStudents().entrySet().iterator(); return new Iterator<CtxStudent>() { public boolean hasNext() { return studentIterator.hasNext(); } public CtxStudent next() { return student(studentIterator.next().getValue()); } public void remove() { studentIterator.remove(); } }; } }; } public CtxStudent student( final Student student ) { final CtxStudent ctxStudent = new CtxStudent( enr, course, group, student ); return propagateTZCache(ctxStudent); } public int days(long anchorMillis, long diffMillis) { final DateTime anchorStartOfDay = startOfDay(anchorMillis); final DateTime anchorEndOfDay = anchorStartOfDay.plusDays(1); final DateTime diffDate = dateTime(diffMillis); // the diffed instant is earlier that start of anchor day if (anchorStartOfDay.isAfter(diffDate)) { // -1 is due to returning number of full days within the interval return -1 - Days.daysBetween( diffDate, anchorStartOfDay ).getDays(); } // within start-end of anchor day return 0 days difference if (anchorEndOfDay.isAfter(diffDate)) { return 0; } // number of full days in the interval, hence +1 return 1 + Days.daysBetween(anchorEndOfDay, diffDate).getDays(); } public DateTime dateTime(long diffMillis) { return new DateTime(diffMillis, dateTimeZone()); } public static String dateTimeNice(final DateTime fromDateTime) { return FMT_DATE_TIME_NICE.print(fromDateTime); } public String dateTimeNice(final long millis) { return dateTimeNice(dateTime(millis)); } public DateTime startOfDay(long anchorMillis) { final DateTime date = dateTime(anchorMillis); final DateTime anchorStartOfDay = new DateTime( date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), 0, 0, 0, 0, dateTimeZone() ); return anchorStartOfDay; } public DateTime endOfDay(long anchorMillis) { final DateTime anchorEndOfDay = startOfDay(anchorMillis).plusDays(1); return anchorEndOfDay; } protected <C extends CtxEnrollment> C propagateTZCache(C ctx) { ctx.timeZoneCache = timeZone(); ctx.dateTimeZoneCache = dateTimeZone(); return ctx; } private DateTimeZone dateTimeZoneCache; public synchronized DateTimeZone dateTimeZone() { if (dateTimeZoneCache != null) { return dateTimeZoneCache; } dateTimeZoneCache = DateTimeZone.forTimeZone(timeZone()); return dateTimeZoneCache; } private TimeZone timeZoneCache; public synchronized TimeZone timeZone() { if (timeZoneCache != null) { return timeZoneCache; } final String enrTZ = enr.getTimeZone(); final boolean tzEmpty = enrTZ == null || enrTZ.trim().length() == 0; timeZoneCache = tzEmpty ? TimeZone.getDefault() : TimeZone.getTimeZone(enrTZ); return timeZoneCache; } }