001 package org.hackystat.projectbrowser.page.dailyprojectdata; 002 003 import java.io.Serializable; 004 import java.text.SimpleDateFormat; 005 import java.util.ArrayList; 006 import java.util.Arrays; 007 import java.util.Date; 008 import java.util.HashMap; 009 import java.util.List; 010 import java.util.Locale; 011 import java.util.Map; 012 import java.util.logging.Logger; 013 014 import org.apache.wicket.PageParameters; 015 import org.hackystat.projectbrowser.ProjectBrowserSession; 016 import org.hackystat.projectbrowser.page.ProjectBrowserBasePage; 017 import org.hackystat.projectbrowser.page.contextsensitive.ContextSensitiveMenu; 018 import org.hackystat.projectbrowser.page.contextsensitive.ContextSensitivePanel; 019 import org.hackystat.projectbrowser.page.dailyprojectdata.build.BuildDataModel; 020 import org.hackystat.projectbrowser.page.dailyprojectdata.commit.CommitDataModel; 021 import org.hackystat.projectbrowser.page.dailyprojectdata.complexity.ComplexityDataModel; 022 import org.hackystat.projectbrowser.page.dailyprojectdata.coupling.CouplingDataModel; 023 import org.hackystat.projectbrowser.page.dailyprojectdata.coverage.CoverageDataModel; 024 import org.hackystat.projectbrowser.page.dailyprojectdata.devtime.DevTimeDataModel; 025 import org.hackystat.projectbrowser.page.dailyprojectdata.filemetric.FileMetricDataModel; 026 import org.hackystat.projectbrowser.page.dailyprojectdata.issue.IssueDataModel; 027 import org.hackystat.projectbrowser.page.dailyprojectdata.unittest.UnitTestDataModel; 028 import org.hackystat.sensorbase.resource.projects.jaxb.Project; 029 import org.hackystat.utilities.tstamp.Tstamp; 030 031 /** 032 * Session instance for the daily project data page to hold its state. 033 * @author Philip Johnson 034 * @author Shaoxuan Zhang 035 */ 036 public class DailyProjectDataSession implements Serializable { 037 038 /** Support serialization. */ 039 private static final long serialVersionUID = 1L; 040 041 /** The parameter key of dpd analysis. */ 042 public static final String ANALYSIS_KEY = "0"; 043 /** The parameter key of date. */ 044 public static final String DATE_KEY = "1"; 045 /** The parameter key of selectedProjects. */ 046 public static final String SELECTED_PROJECTS_KEY = "2"; 047 /** 048 * The last parameter key that is required. 049 */ 050 private static final String LAST_REQUIRED_KEY = "2"; 051 052 /** The parameter instruction message. */ 053 public static final String PARAMETER_ORDER_MESSAGE = "Correct parameter order is : " 054 + "/<analysis>/<date>/<projects>"; 055 056 /** Error message when parsing page paramters. */ 057 private String paramErrorMessage = ""; 058 059 /** The date this user has selected in the ProjectDate form. */ 060 private long date = ProjectBrowserBasePage.getDateYesterday().getTime(); 061 062 /** The projects this user has selected. */ 063 private List<Project> selectedProjects = new ArrayList<Project>(); 064 065 /** The analysis this user has selected. Defaults to Build. */ 066 private String analysis = "Coverage"; 067 068 /** The list of analysis choices. */ 069 private static final List<String> analysisList = 070 Arrays.asList("Build", "Commit", "Coupling", "Coverage", "Complexity", "DevTime", "FileMetric", 071 "Issue", "UnitTest"); 072 073 /** the feedback string. */ 074 private String feedback = ""; 075 076 /** The context sensitive panel. We keep a pointer to this in the session for Ajax updating. */ 077 private ContextSensitivePanel csPanel; 078 079 /** Holds the state of the context-sensitive menus in the context sensitive panel. */ 080 private Map<String, ContextSensitiveMenu> csMenus = new HashMap<String, ContextSensitiveMenu>(); 081 082 /** The Coverage data model. */ 083 private CoverageDataModel coverageDataModel = new CoverageDataModel(); 084 085 /** The Unit Test analysis data model. */ 086 private UnitTestDataModel unitTestDataModel = new UnitTestDataModel(); 087 088 /** The coupling data model. */ 089 private CouplingDataModel couplingDataModel = new CouplingDataModel(); 090 091 /** The complexity data model. */ 092 private ComplexityDataModel complexityDataModel = new ComplexityDataModel(); 093 094 /** The build data model. */ 095 private BuildDataModel buildDataModel = new BuildDataModel(); 096 097 /** The DevTime data model. */ 098 private DevTimeDataModel devTimeDataModel = new DevTimeDataModel(); 099 100 /** The FileMetric data model. */ 101 private FileMetricDataModel fileMetricDataModel = new FileMetricDataModel(); 102 103 /** The Commit data model. */ 104 private CommitDataModel commitDataModel = new CommitDataModel(); 105 106 /** The Issue data model. */ 107 private IssueDataModel issueDataModel = new IssueDataModel(); 108 109 /** 110 * Initialize this session, including the list of context-sensitive menus. 111 */ 112 public DailyProjectDataSession() { 113 // Initialize the context sensitive menus. 114 // Since the default analysis is Coverage, the Values and Coverage Type menus are visible. 115 csMenus.put("Values", new ContextSensitiveMenu("Values", "Count", 116 Arrays.asList("Count", "Percentage"), true)); 117 csMenus.put("Coverage Type", new ContextSensitiveMenu("Coverage Type", "Method", 118 Arrays.asList("Block", "Class", "Conditional", "Element", "Line", "Method", "Statement"), 119 true)); 120 csMenus.put("Coupling Type", new ContextSensitiveMenu("Coupling Type", "Afferent+Efferent", 121 Arrays.asList("Afferent", "Efferent", "Afferent+Efferent"), 122 false)); 123 } 124 125 /** 126 * Return the associated DPD analysis with the given telemetry. 127 * @param telemetryName the name of the given telemetry 128 * @return the associated DPD, null if not found a match one. 129 */ 130 public static String getAssociatedDpdAnalysis(final String telemetryName) { 131 if (telemetryName == null || telemetryName.length() <= 0) { 132 return null; 133 } 134 for (String analysis : analysisList) { 135 if (telemetryName.contains(analysis)) { 136 return analysis; 137 } 138 } 139 return null; 140 } 141 /** 142 * Returns a PageParameters instance that represents the content of the input form. 143 * 144 * @return a PageParameters instance. 145 */ 146 public PageParameters getPageParameters() { 147 PageParameters parameters = new PageParameters(); 148 149 parameters.put(ANALYSIS_KEY, this.getAnalysis()); 150 parameters.put(DATE_KEY, ProjectBrowserSession.getFormattedDateString(this.date)); 151 parameters.put(SELECTED_PROJECTS_KEY, 152 ProjectBrowserSession.convertProjectListToString(this.getSelectedProjects())); 153 154 return parameters; 155 } 156 157 /** 158 * Load data from URL parameters into this session. 159 * @param parameters the URL parameters 160 * @return true if all parameters are loaded correctly 161 */ 162 public boolean loadPageParameters(PageParameters parameters) { 163 boolean isLoadSucceed = true; 164 //boolean isDpdLoaded = false; 165 Logger logger = ProjectBrowserSession.get().getLogger(); 166 if (!parameters.containsKey(LAST_REQUIRED_KEY)) { 167 isLoadSucceed = false; 168 String error = "Some parameters are missing, should be " + LAST_REQUIRED_KEY + "\n" + 169 PARAMETER_ORDER_MESSAGE; 170 logger.warning(error); 171 this.paramErrorMessage = error + "\n"; 172 return false; 173 } 174 StringBuffer errorMessage = new StringBuffer(1000); 175 176 // load dpd analysis name 177 if (parameters.containsKey(ANALYSIS_KEY)) { 178 String analysisString = parameters.getString(ANALYSIS_KEY); 179 if (this.getAnalysisList().contains(analysisString)) { 180 this.setAnalysis(analysisString); 181 //isDpdLoaded = true; 182 } 183 else { 184 isLoadSucceed = false; 185 String error = "Analysis from URL parameter is unknown: " + analysisString; 186 logger.warning(error); 187 errorMessage.append(error); 188 errorMessage.append('\n'); 189 } 190 } 191 else { 192 isLoadSucceed = false; 193 errorMessage.append("Analysis key is missing in URL parameters.\n"); 194 } 195 196 //load dates 197 if (parameters.containsKey(DATE_KEY)) { 198 String startDateString = parameters.getString(DATE_KEY); 199 try { 200 this.date = Tstamp.makeTimestamp(startDateString).toGregorianCalendar() 201 .getTimeInMillis(); 202 } 203 catch (Exception e) { 204 isLoadSucceed = false; 205 String error = "Errors when parsing date from URL parameter: " + startDateString; 206 logger.warning(error + " > " + e.getMessage()); 207 errorMessage.append(error); 208 errorMessage.append('\n'); 209 } 210 } 211 else { 212 isLoadSucceed = false; 213 errorMessage.append("date key is missing in URL parameters.\n"); 214 } 215 216 //load seletecd project 217 if (parameters.containsKey(SELECTED_PROJECTS_KEY)) { 218 String[] projectsStringArray = 219 parameters.getString(SELECTED_PROJECTS_KEY).split( 220 ProjectBrowserSession.PARAMETER_VALUE_SEPARATOR); 221 List<Project> projectsList = new ArrayList<Project>(); 222 for (String projectString : projectsStringArray) { 223 int index = projectString.lastIndexOf(ProjectBrowserSession.PROJECT_NAME_OWNER_SEPARATR); 224 String projectName = projectString; 225 String projectOwner = null; 226 if (index > 0 && index < projectString.length()) { 227 projectName = projectString.substring(0, index); 228 projectOwner = projectString.substring( 229 index + ProjectBrowserSession.PROJECT_NAME_OWNER_SEPARATR.length()); 230 } 231 Project project = ProjectBrowserSession.get().getProject(projectName, projectOwner); 232 if (project == null) { 233 isLoadSucceed = false; 234 String error = "Error URL parameter: project: " + projectString + 235 " >> matching project not found under user: " + 236 ProjectBrowserSession.get().getEmail(); 237 logger.warning(error); 238 errorMessage.append(error); 239 errorMessage.append('\n'); 240 } 241 else { 242 projectsList.add(project); 243 } 244 } 245 if (!projectsList.isEmpty()) { 246 this.setSelectedProjects(projectsList); 247 } 248 } 249 else { 250 isLoadSucceed = false; 251 errorMessage.append("projects is missing in URL parameters.\n"); 252 } 253 254 if (errorMessage.length() > 0) { 255 this.paramErrorMessage = errorMessage.append(PARAMETER_ORDER_MESSAGE).toString(); 256 } 257 return isLoadSucceed; 258 } 259 260 /** 261 * Gets the date associated with this page. 262 * @return The date for this page. 263 */ 264 public Date getDate() { 265 return new Date(this.date); 266 } 267 268 /** 269 * Sets the date associated with this page. 270 * @param date The date for this page. 271 */ 272 public void setDate(Date date) { 273 this.date = date.getTime(); 274 } 275 276 /** 277 * Returns the current date in yyyy-MM-dd format. 278 * @return The date as a simple string. 279 */ 280 public String getDateString() { 281 SimpleDateFormat format = 282 new SimpleDateFormat(ProjectBrowserBasePage.DATA_FORMAT, Locale.ENGLISH); 283 return format.format(new Date(this.date)); 284 } 285 286 287 /** 288 * Returns the list of projects selected by the user. 289 * @return The list of projects selected by the user. 290 */ 291 public List<Project> getSelectedProjects() { 292 return this.selectedProjects; 293 } 294 295 /** 296 * Sets the set of selected projects. 297 * @param projects The projects. 298 */ 299 public void setSelectedProjects(List<Project> projects) { 300 this.selectedProjects = projects; 301 } 302 303 /** 304 * Sets the selected analysis. 305 * @param analysis The analysis to set. 306 */ 307 public void setAnalysis(String analysis) { 308 this.analysis = analysis; 309 } 310 311 /** 312 * Gets the selected analysis. 313 * @return The analysis. 314 */ 315 public String getAnalysis() { 316 return analysis; 317 } 318 319 /** 320 * Returns the list of possible analyses. 321 * @return The analysisList. 322 */ 323 public List<String> getAnalysisList() { 324 return analysisList; 325 } 326 327 /** 328 * Sets the feedback string. 329 * @param feedback The feedback to set. 330 */ 331 public void setFeedback(String feedback) { 332 this.feedback = feedback; 333 } 334 335 /** 336 * Gets the feedback string, and also clears it. 337 * @return The feedback string. 338 */ 339 public String getFeedback() { 340 String returnString = this.feedback; 341 this.feedback = ""; 342 return returnString; 343 } 344 345 /** 346 * Gets all context sensitive menus. 347 * @return The context sensitive menus. 348 */ 349 public List<ContextSensitiveMenu> getContextSensitiveMenus() { 350 return new ArrayList<ContextSensitiveMenu>(this.csMenus.values()); 351 } 352 353 /** 354 * Gets the context sensitive menu with the passed name, or null if not found. 355 * @param name The name of the context sensitive menu. 356 * @return The menu instance, or null if not found. 357 */ 358 public ContextSensitiveMenu getContextSensitiveMenu(String name) { 359 return this.csMenus.get(name); 360 } 361 362 /** 363 * Get the context sensitive panel holding the context sensitive menus. 364 * @return The context sensitive panel. 365 */ 366 public ContextSensitivePanel getContextSensitivePanel() { 367 return this.csPanel; 368 } 369 370 /** 371 * Sets the panel containing the context sensitive menus. 372 * @param panel The panel. 373 */ 374 public void setContextSensitivePanel(ContextSensitivePanel panel) { 375 this.csPanel = panel; 376 } 377 378 /** 379 * Get the Coverage data model. 380 * @return The Coverage data model associated with this session. 381 */ 382 public CoverageDataModel getCoverageDataModel() { 383 return this.coverageDataModel; 384 } 385 386 /** 387 * Gets the Unit test model associated with this session. 388 * @return The Unit Test model. 389 */ 390 public UnitTestDataModel getUnitTestDataModel() { 391 return this.unitTestDataModel; 392 } 393 394 395 /** 396 * Gets the Coupling model associated with this session. 397 * @return The Coupling model. 398 */ 399 public CouplingDataModel getCouplingDataModel() { 400 return this.couplingDataModel; 401 } 402 403 /** 404 * Gets the Complexity model associated with this session. 405 * @return The Complexity model. 406 */ 407 public ComplexityDataModel getComplexityDataModel() { 408 return this.complexityDataModel; 409 } 410 411 /** 412 * Gets the Build model associated with this session. 413 * @return The Build model. 414 */ 415 public BuildDataModel getBuildDataModel() { 416 return this.buildDataModel; 417 } 418 419 /** 420 * Gets the DevTime model associated with this session. 421 * @return The DevTime model. 422 */ 423 public DevTimeDataModel getDevTimeDataModel() { 424 return this.devTimeDataModel; 425 } 426 427 /** 428 * Gets the FileMetric model associated with this session. 429 * @return The FileMetric model. 430 */ 431 public FileMetricDataModel getFileMetricDataModel() { 432 return this.fileMetricDataModel; 433 } 434 435 /** 436 * Gets the Commit model associated with this session. 437 * @return The Commit model. 438 */ 439 public CommitDataModel getCommitDataModel() { 440 return this.commitDataModel; 441 } 442 443 /** 444 * Gets the Issue model associated with this session. 445 * @return The Issue model. 446 */ 447 public IssueDataModel getIssueDataModel() { 448 return this.issueDataModel; 449 } 450 451 /** 452 * @return the paramErrorMessage 453 */ 454 public String getParamErrorMessage() { 455 String temp = this.paramErrorMessage; 456 this.clearParamErrorMessage(); 457 return temp; 458 } 459 460 /** 461 * Clears the paramErrorMessage. 462 */ 463 public void clearParamErrorMessage() { 464 this.paramErrorMessage = ""; 465 } 466 467 /** 468 * Sets all analysis data models to their empty state. 469 */ 470 public void clearDataModels() { 471 this.coverageDataModel.clear(); 472 this.unitTestDataModel.clear(); 473 this.couplingDataModel.clear(); 474 this.complexityDataModel.clear(); 475 this.buildDataModel.clear(); 476 this.devTimeDataModel.clear(); 477 this.fileMetricDataModel.clear(); 478 this.commitDataModel.clear(); 479 } 480 }