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 }