001    package org.hackystat.projectbrowser.page.trajectory.inputpanel;
002    
003    import java.util.logging.Level;
004    import java.util.logging.Logger;
005    
006    import org.apache.wicket.Application;
007    import org.apache.wicket.Component;
008    import org.apache.wicket.extensions.markup.html.form.DateTextField;
009    import org.apache.wicket.extensions.yui.calendar.DatePicker;
010    import org.apache.wicket.markup.ComponentTag;
011    import org.apache.wicket.markup.html.basic.Label;
012    import org.apache.wicket.markup.html.form.Button;
013    import org.apache.wicket.markup.html.form.CheckBox;
014    import org.apache.wicket.markup.html.form.DropDownChoice;
015    import org.apache.wicket.markup.html.form.Form;
016    import org.apache.wicket.markup.html.form.ListChoice;
017    import org.apache.wicket.markup.html.form.TextField;
018    import org.apache.wicket.markup.html.list.ListItem;
019    import org.apache.wicket.markup.html.list.ListView;
020    import org.apache.wicket.model.Model;
021    import org.apache.wicket.model.PropertyModel;
022    import org.hackystat.projectbrowser.ProjectBrowserApplication;
023    import org.hackystat.projectbrowser.ProjectBrowserSession;
024    import org.hackystat.projectbrowser.page.ProjectBrowserBasePage;
025    import org.hackystat.projectbrowser.page.popupwindow.PopupWindowPanel;
026    import org.hackystat.projectbrowser.page.trajectory.TrajectoryProjectChoiceRenderer;
027    import org.hackystat.projectbrowser.page.trajectory.TrajectorySession;
028    import org.hackystat.projectbrowser.page.trajectory.validator.ProjectRecordDateValidator;
029    import org.hackystat.projectbrowser.page.trajectory.validator.TelemetrySelectionValidator;
030    import org.hackystat.telemetry.service.resource.chart.jaxb.ParameterDefinition;
031    import org.hackystat.telemetry.service.resource.chart.jaxb.Type;
032    
033    /**
034     * Input panel for the Trajectory viewer. Includes: project1, project2, intervals, telemetry name,
035     * granularity and parameters.
036     * 
037     * @author Shaoxuan Zhang, Pavel Senin
038     */
039    public class TrajectoryInputForm extends Form {
040    
041      /** Support serialization. */
042      public static final long serialVersionUID = 1L;
043      /** The page containing this form. */
044      private ProjectBrowserBasePage page = null;
045      /** TelemetrySession that holds page state for telemetry. */
046      private TrajectorySession session = ProjectBrowserSession.get().getTrajectorySession();
047    
048      /**
049       * Create this form, supplying the wicket:id.
050       * 
051       * @param id The wicket:id.
052       * @param p the page this page is attached to.
053       */
054      public TrajectoryInputForm(String id, ProjectBrowserBasePage p) {
055    
056        super(id);
057        this.page = p;
058    
059        // set Projects selection to Default if null
060        // i've not yet fixed all of this for two projects
061        if (null == session.getSelectedProject1().getProject()) {
062          session.getSelectedProject1().setProject(ProjectBrowserSession.get().getDefaultProject());
063        }
064        if (null == session.getSelectedProject2().getProject()) {
065          session.getSelectedProject2().setProject(ProjectBrowserSession.get().getDefaultProject());
066        }
067    
068        addProject1Pane();
069    
070        addProject2Pane();
071    
072        addTelemetryPane();
073    
074        Button submitButton = new Button("submit") {
075          /** Support serialization. */
076          public static final long serialVersionUID = 1L;
077    
078          @Override
079          public void onSubmit() {
080            getLogger().log(Level.FINER,
081                "[DEBUG] TrajectoryInputForm: " + "SUBMIT HIT -> updating the TrajectorySession.");
082            ProjectBrowserSession.get().getTrajectorySession().updateDataModel();
083            page.onProjectDateSubmit();
084          }
085    
086          @Override
087          public boolean isEnabled() {
088            return getIsEnable();
089          }
090        };
091        add(submitButton);
092    
093      }
094    
095      /**
096       * Add the project1 related fields to the pane.
097       */
098      private void addProject1Pane() {
099    
100        // Create the drop-down menu for projects.
101        ListChoice projectMenu = new ListChoice("project1List", new PropertyModel(session,
102            "selectedProject1"), new PropertyModel(session, "projectList"),
103            new TrajectoryProjectChoiceRenderer()) {
104          /** Support serialization. */
105          public static final long serialVersionUID = 1L;
106    
107          @Override
108          public boolean isEnabled() {
109            return getIsEnable();
110          }
111        };
112        projectMenu.setRequired(true);
113        add(projectMenu);
114    
115        // StartDateTextField
116        DateTextField startDateTextField = new DateTextField("project1StartDate", new PropertyModel(
117            session, "project1StartDate"), ProjectBrowserBasePage.DATA_FORMAT) {
118          /** Support serialization. */
119          public static final long serialVersionUID = 1L;
120    
121          @Override
122          public boolean isEnabled() {
123            return getIsEnable();
124          }
125        };
126        startDateTextField.add(new DatePicker());
127        startDateTextField.setRequired(true);
128        add(startDateTextField);
129    
130        // EndDateTextField
131        DateTextField endDateTextField = new DateTextField("project1EndDate", new PropertyModel(
132            session, "project1EndDate"), ProjectBrowserBasePage.DATA_FORMAT) {
133          /** Support serialization. */
134          public static final long serialVersionUID = 1L;
135    
136          @Override
137          public boolean isEnabled() {
138            return getIsEnable();
139          }
140        };
141        endDateTextField.add(new DatePicker());
142        endDateTextField.setRequired(true);
143        add(endDateTextField);
144    
145        // Add a validator that makes sure the date interval is within all project intervals.
146        // add(new ProjectDateValidator(projectMenu, startDateTextField, endDateTextField));
147    
148        // indent for the dates
149        TextField indentTextField = new TextField("project1Indent", new PropertyModel(session,
150            "project1Indent"), java.lang.Integer.class) {
151          /** Support serialization. */
152          public static final long serialVersionUID = 1L;
153    
154          @Override
155          public boolean isEnabled() {
156            return getIsEnable();
157          }
158        };
159        indentTextField.setRequired(false);
160        add(indentTextField);
161    
162        // Add a validator that makes sure the date interval is within all project intervals.
163        add(new ProjectRecordDateValidator(projectMenu, startDateTextField, endDateTextField,
164            indentTextField));
165      }
166    
167      /**
168       * Add project2 related fields to the pane.
169       */
170      private void addProject2Pane() {
171        // Create the drop-down menu for projects.
172        ListChoice projectMenu = new ListChoice("project2List", new PropertyModel(session,
173            "selectedProject2"), new PropertyModel(session, "projectList"),
174            new TrajectoryProjectChoiceRenderer()) {
175    
176          /** Support serialization. */
177          public static final long serialVersionUID = 1L;
178    
179          @Override
180          public boolean isEnabled() {
181            return getIsEnable();
182          }
183        };
184        projectMenu.setRequired(true);
185        add(projectMenu);
186    
187        // StartDateTextField
188        DateTextField startDateTextField = new DateTextField("project2StartDate", new PropertyModel(
189            session, "project2StartDate"), ProjectBrowserBasePage.DATA_FORMAT) {
190          /** Support serialization. */
191          public static final long serialVersionUID = 1L;
192    
193          @Override
194          public boolean isEnabled() {
195            return getIsEnable();
196          }
197        };
198        startDateTextField.add(new DatePicker());
199        startDateTextField.setRequired(true);
200        add(startDateTextField);
201    
202        // EndDateTextField
203        DateTextField endDateTextField = new DateTextField("project2EndDate", new PropertyModel(
204            session, "project2EndDate"), ProjectBrowserBasePage.DATA_FORMAT) {
205          /** Support serialization. */
206          public static final long serialVersionUID = 1L;
207    
208          @Override
209          public boolean isEnabled() {
210            return getIsEnable();
211          }
212        };
213        endDateTextField.add(new DatePicker());
214        endDateTextField.setRequired(true);
215        add(endDateTextField);
216    
217        // indent for the dates
218        TextField indentTextField = new TextField("project2Indent", new PropertyModel(session,
219            "project2Indent"), java.lang.Integer.class) {
220          /** Support serialization. */
221          public static final long serialVersionUID = 1L;
222    
223          @Override
224          public boolean isEnabled() {
225            return getIsEnable();
226          }
227        };
228        indentTextField.setRequired(false);
229        add(indentTextField);
230    
231        // Add a validator that makes sure the date interval is within all project intervals.
232        add(new ProjectRecordDateValidator(projectMenu, startDateTextField, endDateTextField,
233            indentTextField));
234      }
235    
236      /**
237       * Add telemetry related stuff to the pane.
238       */
239      private void addTelemetryPane() {
240        // Create the drop-down menu for telemetry chart selection.
241        //
242        DropDownChoice telemetryMenu = new DropDownChoice("telemetryMenu", new PropertyModel(session,
243            "telemetryName"), new PropertyModel(session, "telemetryList")) {
244          /** Support serialization. */
245          private static final long serialVersionUID = 1L;
246    
247          @Override
248          protected boolean wantOnSelectionChangedNotifications() {
249            return true;
250          }
251    
252          @Override
253          protected void onSelectionChanged(java.lang.Object newSelection) {
254            session.getParameters().clear();
255          }
256    
257          @Override
258          public boolean isEnabled() {
259            return getIsEnable();
260          }
261        };
262        telemetryMenu.setRequired(true);
263        add(new TelemetrySelectionValidator(telemetryMenu));
264        add(telemetryMenu);
265        // add the popup window
266        PopupWindowPanel telemetryPopup = new PopupWindowPanel("chartDefPopup",
267            "Telemetry Descriptions");
268        telemetryPopup.getModalWindow().setContent(
269            new TrajectoryDescriptionPanel(telemetryPopup.getModalWindow().getContentId()));
270        add(telemetryPopup);
271        if (session.getTelemetryName() == null && !session.getTelemetryList().isEmpty()) {
272          session.setTelemetryName(session.getTelemetryList().get(0));
273        }
274    
275        // granularity
276        add(new DropDownChoice("granularity", new PropertyModel(session, "granularity"), session
277            .getGranularityList()) {
278          /** Support serialization. */
279          public static final long serialVersionUID = 1L;
280    
281          @Override
282          public boolean isEnabled() {
283            return getIsEnable();
284          }
285        });
286    
287        // Add parameter List
288        ListView parameterList = new ListView("parameterList", new PropertyModel(session,
289            "parameterList")) {
290          /** Support serialization. */
291          public static final long serialVersionUID = 1L;
292    
293          @Override
294          protected void populateItem(ListItem item) {
295            ParameterDefinition paramDef = (ParameterDefinition) item.getModelObject();
296            item.add(new Label("name", paramDef.getName()));
297            Component component = getComponent("field", paramDef.getType());
298            if (item.getIndex() >= session.getParameters().size() && component.getModel() != null) {
299              session.getParameters().add(component.getModel());
300            }
301            else {
302              component.setModel(session.getParameters().get(item.getIndex()));
303            }
304            item.add(component);
305            PopupWindowPanel parameterPopup = 
306                                            new PopupWindowPanel("parameterPopup", paramDef.getName());
307            parameterPopup.getModalWindow().setContent(
308                new Label(parameterPopup.getModalWindow().getContentId(), paramDef.getDescription()));
309            item.add(parameterPopup);
310          }
311    
312          @Override
313          public boolean isVisible() {
314            return getIsEnable();
315          }
316        };
317        add(parameterList);
318    
319      }
320    
321      /**
322       * Disable the whole form when data loading in process.
323       * 
324       * @return true if the form is enabled.
325       */
326      @Override
327      public boolean isEnabled() {
328        return getIsEnable();
329      }
330    
331      /**
332       * @return true if the form is enabled.
333       */
334      protected final boolean getIsEnable() {
335        return !ProjectBrowserSession.get().getTelemetrySession().getDataModel().isInProcess();
336      }
337    
338      /**
339       * Return a FormComponent according to the parameter type. DropDownChoice for Enumerated. CheckBox
340       * for Boolean. TextField for Text and Integer.
341       * 
342       * @param id the wicket component id.
343       * @param type the parameter type.
344       * @return a FormComponent.
345       */
346      public final Component getComponent(String id, Type type) {
347        Component component;
348        if ("Enumerated".equals(type.getName())) {
349          DropDownChoice choice = new DropDownChoice(id, new Model(type.getDefault()), 
350                                                                              type.getValue()) {
351            /** Support serialization. */
352            public static final long serialVersionUID = 1L;
353    
354            /**
355             * Called any time a component that has this behavior registered is rendering the component
356             * tag.
357             * 
358             * @param tag the tag that is rendered
359             */
360            @Override
361            protected void onComponentTag(ComponentTag tag) {
362              tag.setName("select");
363              super.onComponentTag(tag);
364            }
365          };
366          // choice.setPersistent(true);
367          component = choice;
368        }
369        else if ("Boolean".equals(type.getName())) {
370          CheckBox checkBox = new CheckBox(id, new Model(type.getDefault())) {
371            /** Support serialization. */
372            public static final long serialVersionUID = 1L;
373    
374            @Override
375            protected void onComponentTag(ComponentTag tag) {
376              tag.setName("input");
377              tag.put("type", "checkbox");
378              tag.remove("style"); // need for firefox on mac.
379              super.onComponentTag(tag);
380            }
381          };
382          // checkBox.setPersistent(true);
383          component = checkBox;
384        }
385        else if ("Text".equals(type.getName()) || "Integer".equals(type.getName())) {
386          TextField textField = new TextField(id, new Model(type.getDefault())) {
387            /** Support serialization. */
388            public static final long serialVersionUID = 1L;
389    
390            @Override
391            protected void onComponentTag(ComponentTag tag) {
392              tag.setName("input");
393              tag.put("type", "text");
394              super.onComponentTag(tag);
395            }
396          };
397          // textField.setPersistent(true);
398          component = textField;
399        }
400        else {
401          component = new Label(id, new Model("Parameter Type " + type.getName() + " not recognized."));
402        }
403        return component;
404      }
405    
406      /**
407       * @return the logger that associated to this web application.
408       */
409      private Logger getLogger() {
410        return ((ProjectBrowserApplication) Application.get()).getLogger();
411      }
412    
413    }