001    package org.hackystat.projectbrowser.page.trajectory.datapanel;
002    
003    import java.text.SimpleDateFormat;
004    import java.util.ArrayList;
005    import java.util.List;
006    import java.util.Locale;
007    import java.util.logging.Level;
008    import java.util.logging.Logger;
009    
010    import javax.xml.datatype.XMLGregorianCalendar;
011    
012    import org.apache.wicket.Application;
013    import org.apache.wicket.AttributeModifier;
014    import org.apache.wicket.markup.html.WebComponent;
015    import org.apache.wicket.markup.html.basic.Label;
016    import org.apache.wicket.markup.html.form.Button;
017    import org.apache.wicket.markup.html.form.CheckBox;
018    import org.apache.wicket.markup.html.form.Form;
019    import org.apache.wicket.markup.html.link.BookmarkablePageLink;
020    import org.apache.wicket.markup.html.list.ListItem;
021    import org.apache.wicket.markup.html.list.ListView;
022    import org.apache.wicket.markup.html.panel.Panel;
023    import org.apache.wicket.model.IModel;
024    import org.apache.wicket.model.Model;
025    import org.apache.wicket.model.PropertyModel;
026    import org.hackystat.projectbrowser.ProjectBrowserApplication;
027    import org.hackystat.projectbrowser.ProjectBrowserSession;
028    import org.hackystat.projectbrowser.imageurl.ImageUrl;
029    import org.hackystat.projectbrowser.page.popupwindow.PopupWindowPanel;
030    import org.hackystat.projectbrowser.page.trajectory.ProjectRecord;
031    import org.hackystat.projectbrowser.page.trajectory.TrajectoryPage;
032    import org.hackystat.projectbrowser.page.trajectory.TrajectorySession;
033    import org.hackystat.sensorbase.resource.projects.jaxb.Project;
034    import org.hackystat.telemetry.service.resource.chart.jaxb.TelemetryPoint;
035    import org.hackystat.utilities.tstamp.Tstamp;
036    
037    /**
038     * Panel for showing telemetry content.
039     *
040     * @author Shaoxuan Zhang, Pavel Senin
041     *
042     */
043    public class TrajectoryDataPanel extends Panel {
044      /** Support serialization. */
045      private static final long serialVersionUID = 1L;
046      /** The page containing this form. */
047      private TrajectoryPage page = null;
048      /** TelemetrySession that hold the page state. */
049      TrajectorySession session = ProjectBrowserSession.get().getTrajectorySession();
050    
051      /**
052       * @param id the wicket component id.
053       * @param p the page this page is attached to.
054       */
055      public TrajectoryDataPanel(String id, TrajectoryPage p) {
056        super(id);
057        this.page = p;
058        getLogger().log(
059            Level.FINER,
060            "[DEBUG] TrajectoryDataPanel constructed: INPROCESS: "
061                + session.getDataModel().isInProcess() + ", COMPLETE: "
062                + session.getDataModel().isComplete());
063        try {
064          while ((session.getDataModel().isInProcess()) && (!session.getDataModel().isComplete())) {
065            getLogger().log(Level.FINER, "[DEBUG] sleeping for a sec");
066            Thread.sleep(1000);
067          }
068        }
069        catch (InterruptedException e) {
070          // TODO Auto-generated catch block
071          e.printStackTrace();
072        }
073        
074        IModel dataModel = new PropertyModel(session, "dataModel");
075        
076        BookmarkablePageLink restLink = new BookmarkablePageLink("restLink", TrajectoryPage.class,
077            session.getPageParameters());
078    
079        // restLink.add(new Label("restLinkLabel", new Model(restLink)));
080        add(restLink);
081    
082        Form streamForm = new Form("streamForm") {
083          /** Support serialization. */
084          private static final long serialVersionUID = 1L;
085    
086          @Override
087          public void onSubmit() {
088            if (!session.getDataModel().updateSelectedChart()) {
089              session.setFeedback("Failed to get a chart image. "
090                  + " Please check to make sure you've selected at least one stream!");
091            }
092          }
093        };
094    
095        Button submitButton = new Button("dtw") {
096          /** Support serialization. */
097          public static final long serialVersionUID = 1L;
098    
099          @Override
100          public void onSubmit() {
101            getLogger().log(Level.FINER, "[DEBUG] DTW is HIT");
102            if ((session.getDataModel().updateSelectedChart())
103                && (session.getDataModel().updateNormalizedTSChart())
104                && (session.getDataModel().updateDTWChart())) {
105              page.goDTW();
106            }
107            else {
108              session.setFeedback("Failed to start analysis dialog. "
109                  + " Please check to make sure you've selected at least one stream!");
110            }
111          }
112    
113        };
114        submitButton.setDefaultFormProcessing(false);
115        streamForm.add(submitButton);
116    
117        add(streamForm);
118        // table headers
119        add(new Label("telemetryName", new PropertyModel(dataModel, "telemetryName")));
120    
121        ListView markersList = new ListView("markersList",
122            new PropertyModel(dataModel, "markersList")) {
123          /** Support serialization. */
124          public static final long serialVersionUID = 1L;
125    
126          @Override
127          protected void populateItem(ListItem item) {
128            String dateString = (String) item.getModelObject();
129            item.add(new Label("marker", dateString));
130          }
131        };
132        streamForm.add(markersList);
133    
134        // checkbox to select stream to display
135        streamForm.add(new CheckBox("selectAll", new Model()) {
136          /** Support serialization. */
137          public static final long serialVersionUID = 1L;
138    
139          @Override
140          protected void onSelectionChanged(java.lang.Object newSelection) {
141            session.getDataModel().changeSelectionForAll((Boolean) newSelection);
142          }
143    
144          @Override
145          protected boolean wantOnSelectionChangedNotifications() {
146            return true;
147          }
148        });
149    
150        // stream data
151        ListView projectTable = new ListView("projectTable", new PropertyModel(dataModel,
152            "selectedProjects")) {
153          /** Support serialization. */
154          public static final long serialVersionUID = 1L;
155    
156          @Override
157          protected void populateItem(ListItem item) {
158            final ProjectRecord projectRecord = (ProjectRecord) item.getModelObject();
159            Project project = projectRecord.getProject();
160            Label projectNameLabel = new Label("projectName", project.getName());
161            List<SelectableTrajectoryStream> streamList = session.getDataModel().getTrajectoryStream(
162                project);
163            projectNameLabel.add(new AttributeModifier("rowspan", new Model(streamList.size() + 1)));
164            item.add(projectNameLabel);
165            ListView datesList = new ListView("datesList", getDateList(projectRecord.getIndent(),
166                streamList.get(0).getTelemetryStream().getTelemetryPoint())) {
167              /** Support serialization. */
168              public static final long serialVersionUID = 1L;
169    
170              @Override
171              protected void populateItem(ListItem item) {
172                String date = (String) item.getModelObject();
173                item.add(new Label("date", date));
174              }
175            };
176            item.add(datesList);
177    
178            ListView projectStream = new ListView("projectStream", streamList) {
179              /** Support serialization. */
180              public static final long serialVersionUID = 1L;
181    
182              @Override
183              protected void populateItem(ListItem item) {
184                SelectableTrajectoryStream stream = (SelectableTrajectoryStream) item.getModelObject();
185                String streamName = stream.getTelemetryStream().getName();
186                String streamUnit = stream.getTelemetryStream().getYAxis().getUnits();
187                /*
188                 * int index = streamName.indexOf('<'); if (index > 0) { streamName =
189                 * streamName.substring(0, index); }
190                 */
191                item.add(new Label("streamName", streamName));
192    
193                item.add(new Label("streamUnit", streamUnit));
194    
195                /*
196                 * WebComponent streamMarker = new WebComponent("streamMarker"); streamMarker.add(new
197                 * AttributeModifier("src", true, new PropertyModel(stream, "markerImageUrl")));
198                 * item.add(streamMarker);
199                 */
200    
201                item.add(new ImageUrl("streamMarker", stream.getMarkerImageUrl()));
202    
203                WebComponent colorCell = new WebComponent("colorCell");
204                colorCell.add(new AttributeModifier("style", true, new PropertyModel(stream,
205                    "backgroundColorValue")));
206                item.add(colorCell);
207    
208                item.add(new CheckBox("streamCheckBox", new PropertyModel(stream, "selected")));
209    
210                ListView streamData = new ListView("streamData", getValuesList(projectRecord
211                    .getIndent(), stream.getTelemetryStream().getTelemetryPoint())) {
212                  /** Support serialization. */
213                  public static final long serialVersionUID = 1L;
214    
215                  @Override
216                  protected void populateItem(ListItem item) {
217                    String value = (String) item.getModelObject();
218                    item.add(new Label("data", value));
219                  }
220                };
221                item.add(streamData);
222              }
223            };
224            item.add(projectStream);
225          }
226        };
227        streamForm.add(projectTable);
228        
229        add(new Label("streamWarningMessage", new PropertyModel(dataModel, "warningMessage")));
230    
231        // add the selected chart.
232        WebComponent selectedchartUrl = new WebComponent("selectedChart") {
233          /** Support serialization. */
234          public static final long serialVersionUID = 1L;
235    
236          @Override
237          public boolean isVisible() {
238            return !session.getDataModel().isChartEmpty();
239          }
240        };
241        selectedchartUrl.add(new AttributeModifier("src", true, new PropertyModel(dataModel,
242            "selectedChart")));
243        add(selectedchartUrl);
244    
245        PopupWindowPanel selectedchartUrlWindow = new PopupWindowPanel("selectedChartUrlWindow",
246            "Google Chart URL") {
247          /** Support serialization. */
248          public static final long serialVersionUID = 1L;
249    
250          @Override
251          public boolean isVisible() {
252            return !session.getDataModel().isChartEmpty();
253          }
254        };
255        selectedchartUrlWindow.getModalWindow().setContent(
256            new Label(selectedchartUrlWindow.getModalWindow().getContentId(), new PropertyModel(
257                dataModel, "selectedChart")));
258        add(selectedchartUrlWindow);
259    
260        // attribute to decide to show panel content or not.
261        /*
262         * AttributeModifier visibleAttribute = new AttributeModifier("style", true, new
263         * AbstractReadOnlyModel() { private static final long serialVersionUID = 2013912742253160111L;
264         *
265         * @Override public Object getObject() { return (!session.getDataModel().isEmpty() &&
266         * session.getDataModel().isComplete()) ? "" : "display:none"; } }); add(visibleAttribute);
267         */
268    
269      }
270    
271      /**
272       * Show the panel only when the data model is not empty and no loading is in process.
273       *
274       * @return true when this panel should be shown.
275       */
276      @Override
277      public boolean isVisible() {
278        return !session.getDataModel().isEmpty() && session.getDataModel().isComplete();
279      }
280    
281      /**
282       * Return the date list within the list of points.
283       *
284       * @param indent the indent.
285       * @param points the point list.
286       * @return the date list.
287       */
288      private List<String> getDateList(Integer indent, List<TelemetryPoint> points) {
289        List<String> dates = new ArrayList<String>();
290        SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd", Locale.US);
291        XMLGregorianCalendar startDate = Tstamp.makeTimestamp(points.get(0).getTime()
292            .toGregorianCalendar().getTimeInMillis());
293        for (int i = indent; i > 0; i--) {
294          dates.add(dateFormat.format(Tstamp.incrementDays(startDate, -i).toGregorianCalendar()
295              .getTime()));
296        }
297        for (TelemetryPoint point : points) {
298          dates.add(dateFormat.format(point.getTime().toGregorianCalendar().getTime()));
299        }
300        return dates;
301      }
302    
303      /**
304       * Return the values list within the list of points.
305       *
306       * @param indent the indent.
307       * @param points the point list.
308       * @return the values list.
309       */
310      private List<String> getValuesList(Integer indent, List<TelemetryPoint> points) {
311        List<String> values = new ArrayList<String>();
312        for (int i = indent; i > 0; i--) {
313          values.add("N/A");
314        }
315        for (TelemetryPoint point : points) {
316          String value = point.getValue();
317          if (value == null) {
318            values.add("N/A");
319          }
320          else {
321            int i = value.indexOf('.');
322            if (i > 0 && (i + 2) < value.length()) {
323              value = value.substring(0, i + 2);
324            }
325            values.add(value);
326          }
327        }
328        return values;
329      }
330    
331      /**
332       * @return the logger that associated to this web application.
333       */
334      private Logger getLogger() {
335        return ((ProjectBrowserApplication) Application.get()).getLogger();
336      }
337    
338    }