001 package org.hackystat.projectbrowser.page.trajectory.validator; 002 003 import java.util.ArrayList; 004 import java.util.Date; 005 import java.util.List; 006 007 import javax.xml.datatype.XMLGregorianCalendar; 008 009 import org.apache.wicket.extensions.markup.html.form.DateTextField; 010 import org.apache.wicket.markup.html.form.Form; 011 import org.apache.wicket.markup.html.form.FormComponent; 012 import org.apache.wicket.markup.html.form.ListChoice; 013 import org.apache.wicket.markup.html.form.ListMultipleChoice; 014 import org.apache.wicket.markup.html.form.validation.AbstractFormValidator; 015 import org.hackystat.projectbrowser.page.trajectory.ProjectRecord; 016 import org.hackystat.sensorbase.resource.projects.ProjectUtils; 017 import org.hackystat.utilities.tstamp.Tstamp; 018 019 /** 020 * Provides a project date validator. This validator will work with forms that have a multiple 021 * selection menu for Projects, plus either one or two date fields. It provides two constructors: 022 * one for forms with a Project menu and one date, and one for forms with a Project menu and two 023 * dates. 024 * 025 * @author Philip Johnson, Pavel Senin 026 */ 027 public class ProjectRecordDateValidator extends AbstractFormValidator { 028 029 /** For serialization. */ 030 private static final long serialVersionUID = 1L; 031 032 /** 033 * Form components to be checked. The first must be the projectMenu (a ListMultipleChoice), the 034 * second must be a date (a DateTextField), and the third (if present) is another DateTextField. 035 * This enables the validator to be used with either forms with a single date (such as DPDs) as 036 * well as forms with a start and end date (such as Telemetry). 037 */ 038 private final FormComponent[] components; 039 040 /** 041 * Takes a Project menu and a single Date field. 042 * 043 * @param projectMenu The project menu component. 044 * @param dateField The Date field component. 045 */ 046 public ProjectRecordDateValidator(FormComponent projectMenu, FormComponent dateField) { 047 if (projectMenu == null) { 048 throw new IllegalArgumentException("projectMenu cannot be null"); 049 } 050 if (dateField == null) { 051 throw new IllegalArgumentException("dateField cannot be null"); 052 } 053 if (!(projectMenu instanceof ListMultipleChoice)) { 054 throw new IllegalArgumentException("ProjectDateValidator not given a ListMultipleChoice"); 055 } 056 if (!(dateField instanceof DateTextField)) { 057 throw new IllegalArgumentException("ProjectDateValidator not given a DateTextField"); 058 } 059 components = new FormComponent[] { projectMenu, dateField }; 060 } 061 062 /** 063 * Takes a Project menu (ListMultipleChoice or ListChoice) and two Date fields (DateTextField). 064 * 065 * @param projectMenu The project menu component. 066 * @param startDateField The Date field component. 067 * @param endDateField The Date field component. 068 */ 069 public ProjectRecordDateValidator(FormComponent projectMenu, FormComponent startDateField, 070 FormComponent endDateField) { 071 if (projectMenu == null) { 072 throw new IllegalArgumentException("projectMenu cannot be null"); 073 } 074 if (startDateField == null) { 075 throw new IllegalArgumentException("startDateField cannot be null"); 076 } 077 if (!((projectMenu instanceof ListMultipleChoice) || (projectMenu instanceof ListChoice))) { 078 throw new IllegalArgumentException("ProjectDateValidator not given a ListMultipleChoice " 079 + "or ListChoice"); 080 } 081 if (!(startDateField instanceof DateTextField)) { 082 throw new IllegalArgumentException("ProjectDateValidator not given a DateTextField"); 083 } 084 if (!(endDateField instanceof DateTextField)) { 085 throw new IllegalArgumentException("ProjectDateValidator not given a DateTextField"); 086 } 087 components = new FormComponent[] { projectMenu, startDateField, endDateField }; 088 } 089 090 /** 091 * Takes a Project menu (ListMultipleChoice or ListChoice) and two Date fields (DateTextField). 092 * 093 * @param projectMenu The project menu component. 094 * @param startDateField The Date field component. 095 * @param endDateField The Date field component. 096 * @param indent The indent for the interval. 097 */ 098 public ProjectRecordDateValidator(FormComponent projectMenu, FormComponent startDateField, 099 FormComponent endDateField, FormComponent indent) { 100 if (projectMenu == null) { 101 throw new IllegalArgumentException("projectMenu cannot be null"); 102 } 103 if (startDateField == null) { 104 throw new IllegalArgumentException("startDateField cannot be null"); 105 } 106 if (!((projectMenu instanceof ListMultipleChoice) || (projectMenu instanceof ListChoice))) { 107 throw new IllegalArgumentException("ProjectDateValidator not given a ListMultipleChoice " 108 + "or ListChoice"); 109 } 110 if (!(startDateField instanceof DateTextField)) { 111 throw new IllegalArgumentException("ProjectDateValidator not given a DateTextField"); 112 } 113 if (!(endDateField instanceof DateTextField)) { 114 throw new IllegalArgumentException("ProjectDateValidator not given a DateTextField"); 115 } 116 components = new FormComponent[] { projectMenu, startDateField, endDateField }; 117 } 118 119 /** 120 * Returns the form components. 121 * 122 * @return The form components. 123 */ 124 public FormComponent[] getDependentFormComponents() { 125 return components.clone(); 126 } 127 128 /** 129 * Performs the validation. Note that this validation must handle a projectMenu plus a single 130 * date, or a projectMenu plus two dates (start and end date). 131 * 132 * @param projectDateForm The form to validate. 133 */ 134 @SuppressWarnings("unchecked") 135 public void validate(Form projectDateForm) { 136 List<ProjectRecord> projects = new ArrayList<ProjectRecord>(); 137 if (components[0] instanceof ListMultipleChoice) { 138 ListMultipleChoice projectMenu = (ListMultipleChoice) components[0]; 139 projects = (List<ProjectRecord>) projectMenu.getConvertedInput(); 140 } 141 else { 142 ListChoice projectMenu = (ListChoice) components[0]; 143 ProjectRecord projectRecord = (ProjectRecord) projectMenu.getConvertedInput(); 144 projects.add(projectRecord); 145 } 146 DateTextField startDateField = (DateTextField) components[1]; 147 DateTextField endDateField = null; 148 if (components.length == 3) { 149 endDateField = (DateTextField) components[2]; 150 } 151 Date date1 = (Date) startDateField.getConvertedInput(); 152 XMLGregorianCalendar tomorrow = Tstamp.incrementDays(Tstamp.makeTimestamp(), 1); 153 Date date2 = null; 154 if (endDateField != null) { 155 date2 = (Date) endDateField.getConvertedInput(); 156 } 157 158 for (ProjectRecord projectRecord : projects) { 159 XMLGregorianCalendar startTime = Tstamp.makeTimestamp(date1.getTime()); 160 if (!ProjectUtils.isValidStartTime(projectRecord.getProject(), startTime)) { // NOPMD 161 error(startDateField, "DateBeforeProjectStartTime"); 162 } 163 else if (!ProjectUtils.isValidEndTime(projectRecord.getProject(), startTime)) { // NOPMD 164 error(startDateField, "DateAfterProjectEndTime"); 165 } 166 else if (Tstamp.greaterThan(startTime, tomorrow)) { 167 error(startDateField, "DateInFuture"); 168 } 169 // Only check the end date if this form actually contained an end date. 170 if (date2 != null) { 171 XMLGregorianCalendar endTime = Tstamp.makeTimestamp(date2.getTime()); 172 if (!ProjectUtils.isValidStartTime(projectRecord.getProject(), endTime)) { // NOPMD 173 error(endDateField, "DateBeforeProjectStartTime"); 174 } 175 else if (!ProjectUtils.isValidEndTime(projectRecord.getProject(), endTime)) { // NOPMD 176 error(endDateField, "DateAfterProjectEndTime"); 177 } 178 else if (Tstamp.greaterThan(endTime, tomorrow)) { 179 error(endDateField, "DateInFuture"); 180 } 181 } 182 } 183 } 184 }