1 /** 2 * A global object which keeps track of user data. 3 * @extends Workbench.component.Component 4 * @author Andrew, Amit Kumar 5 * // added chunkList getters and setters 6 */ 7 8 Monk.component.DataManager = function(args) { 9 10 this.projectId = null; 11 this.worksetId = null; 12 this.toolsetId = null; 13 this.instanceId = null; 14 this.chunkType = null; 15 this.worklist = {}; 16 this.featureList = []; 17 // to store documentlist from the similarity tool 18 // and the search/browse tool 19 this.chunkList = []; 20 //search query parameters are stored here 21 this.queryParam=null; 22 this.decisionTree = ""; 23 this.decisionTreeSummary=""; 24 this.resultSummary=""; 25 this.worksetName = null; 26 this.itinerary = ""; 27 this.feature = ""; 28 this.lastWorksetLoadedTimestamp = 0; 29 this.unsavedWorksetData = false; 30 31 this.currentChunk = null; 32 33 this.projectData = null; 34 35 // parameters used when running analyses 36 this.performingAnalysis = false; 37 this.progressDialog = null; 38 this.cachedData = null; 39 this.token = null; 40 this.jobStatusTimer = null; 41 this.timerInterval = 5000; 42 this.similaritySearchURL = Monk.data.PROXY_URL + "get/AnalyticsManager.getMoreLikeThisWorkset"; 43 this.searchAndBrowseURL = Monk.data.PROXY_URL + "get/SearchManager.getWorksWithFeature"; 44 this.worksetSearchURL = Monk.data.PROXY_URL+"get/WorkSetsManager.getWorkset"; 45 this.simpleSearchURL = Monk.data.PROXY_URL+"get/SearchManager.getWorksWithAnyFeature"; 46 // supports workset/any search criterion the other similarity call will retire 47 this.similarityAllSearchURL = Monk.data.PROXY_URL + "get/AnalyticsManager.getMoreLikeThis"; 48 49 50 // definition of the work record 51 this.workDef = Ext.data.Record.create([ 52 {name: 'id', mapping: '@id'}, 53 {name: 'collection', mapping: '@collection_id'}, 54 {name: 'type', mapping: '@type'}, 55 {name: 'circulationStart', mapping: 'publication/@start'}, 56 {name: 'circulationEnd', mapping: 'publication/@end'}, 57 {name: 'circulationPeriod' ,mapping:'publication/@start',convert: function(value){ 58 var start = Math.floor(value/10)*10; 59 var end = parseInt(start)+10; 60 return start+"-"+end; 61 }}, 62 {name: 'genre', mapping: 'genre'}, 63 {name: 'scoreRange', mapping: 'score', convert: function(value){ 64 var start =Math.floor(value*10)/10; 65 var end = Math.ceil(value*10)/10; 66 return start+"-"+end; 67 }}, 68 {name: 'score', mapping: 'score'}, 69 {name: 'author', mapping: 'authors/author/@id'}, 70 {name: 'authorBirthYear', mapping:'authors/author/@birthdate'}, 71 {name: 'authorDeathYear', mapping:'authors/author/@enddate'}, 72 {name: 'authorGender', mapping:'authors/author/@gender'}, 73 {name: 'label', mapping: 'label'}, // "mapping" property not needed if it's the same as "name" 74 {name: 'workLabel', mapping: 'work_label'} //used by workpart 75 ]); 76 77 // this reads the XML formatted work results 78 this.searchXMLReader = new Ext.ux.ErrorHandlingXmlReader({ 79 totalRecords: "@totalCount", // The element which contains the total dataset size (optional) 80 record: "work", // The repeated element which contains row information 81 id: "@id" // The element within the row that provides an ID for the record (optional) 82 }, this.workDef); 83 84 // the search result store -used by the searchAndbrowse tool and similarity tool 85 this.resultStore = new Ext.data.GroupingStore({ 86 proxy: new Ext.data.HttpProxy( 87 new Ext.data.Connection({ 88 url: Monk.data.PROXY_URL + "get/CorpusManager.getWorksWithFeature", 89 method: 'POST', 90 timeout: 60000 91 }) 92 ) 93 ,listeners: { 94 'beforeload': function(proxy, params){ 95 var li = Ext.getCmp('loading-indicator'); 96 if (li) li.show(); 97 }, 98 'load': function(proxy, data, callback){ 99 var li = Ext.getCmp('loading-indicator'); 100 if (li) li.hide(); 101 }, 102 'loadexception': function(proxy, data, callback, exception){ 103 var li = Ext.getCmp('loading-indicator'); 104 if (li) li.hide(); 105 } 106 } 107 ,reader : this.searchXMLReader 108 ,baseParams: {format:'xml',start: 0, maxDocuments : '-1',limit:1000} 109 ,autoLoad: false 110 ,sortInfo:{field: 'label', direction: "ASC"} 111 ,groupField: 'circulationPeriod' 112 }); 113 114 Monk.component.DataManager.superclass.constructor.call(this, args); 115 } 116 117 Workbench.extend(Monk.component.DataManager, Workbench.component.Component, { 118 label : "Data Manager", 119 description : "For managing data in Monk.", 120 121 getResultStore : function(){ 122 return this.resultStore; 123 }, 124 125 /** 126 * Takes a node from MonkServices and adapts it to what will be the new implementation. 127 * @param {Object} node The node to fix 128 * @param {String} collectionId The ID for the collection this node belongs to 129 * @return {Object} The fixed node 130 */ 131 /* fixNode : function(node, collectionId) { 132 // prepend the collectionId if necessary 133 var id = (node.id == collectionId) ? collectionId : collectionId + "." + node.id; 134 var newNode = { 135 id: id, 136 text: node.label, 137 chunkType: node.type 138 }; 139 return newNode; 140 },*/ 141 142 /** 143 * This applies the fixNode method recursively to a tree of nodes, 144 * and flattens the tree into the passed array. 145 * @param {Object} node The tree root 146 * @param {Array} nodes The resulting collection of nodes 147 */ 148 /* recursiveFix : function(node, nodes) { 149 if (node.length != null) { 150 for (var i=0;i<node.length;i++) { 151 this.recursiveFix(node[i], nodes); 152 } 153 } else if (node.node) { 154 // don't add collections 155 if (node.type != 'collection') nodes.push(this.fixNode(node, this.getCollectionId())); 156 this.recursiveFix(node.node, nodes); 157 } else { 158 if (node.type != 'collection') nodes.push(this.fixNode(node, this.getCollectionId())); 159 } 160 },*/ 161 162 /** 163 * Called when a user checks a chunk. 164 * Adds/removes the chunk to the worklist based on the checked attribute. 165 * @param {Object} chunk The chunk to be processed 166 */ 167 processChunk : function(chunk) { 168 if (chunk.checked != false) { 169 if (this.worklist[chunk.id] == null) { 170 this.worklist[chunk.id] = { 171 chunkType: chunk.chunkType, 172 text: chunk.text, 173 corpus: "" 174 }; 175 } else { 176 this.worklist[chunk.id].chunkType = chunk.chunkType; 177 this.worklist[chunk.id].text = chunk.text; 178 this.worklist[chunk.id].corpus= ""; 179 180 } 181 182 } else { 183 // if the chunk was unchecked then remove it from the list 184 delete this.worklist[chunk.id]; 185 } 186 187 this.unsavedWorksetData = true; 188 }, 189 // returns the document list in the result store 190 getDocumentList: function(){ 191 var documentArray = new Array(Monk.component.dataManager.getResultStore().getCount()); 192 var i=0; 193 Monk.component.dataManager.getResultStore().each(function(record,options){ 194 documentArray[i] = record.data.id; 195 i++; 196 },this); 197 return documentArray; 198 }, 199 200 /**This functions calls the backend to do the analysis 201 * 202 * @param string type /workset/collection or author 203 * @param featureType feature_spelling_gender, feature_lemma_gender 204 * @param {} queryParam 205 */ 206 doFeatureComparison: function(type,featureType,queryParam){ 207 Workbench.console.info("here do the comparison... " + type + " " + featureType + " " + queryParam); 208 209 var featureQueryParam={"featureType":featureType}; 210 featureQueryParam["queryTypes"]=type; 211 if(type=="collection"){ 212 featureQueryParam["queryValues"]=queryParam.corpusCriterion; 213 }else if(type=="workset"){ 214 featureQueryParam["queryValues"]=queryParam; 215 } 216 /* 217 Monk.chart.getFeatureComparison(type,featureType,featureQueryParam); 218 Ext.ux.ErrorHandlingConnection 219 Workbench.component.manager.notify(new Monk.event.chart.FeatureComparisonChartRetrieved({ 220 label: 'compare features: ' 221 }), {"featureType":featureType,"imgUrl":"http://www.google.com/intl/en_ALL/images/logo.gif"}); 222 */ 223 Monk.chart.getFeatureComparison(type,featureType,featureQueryParam); 224 225 }, 226 227 /** 228 * Set query param 229 */ 230 setSearchQueryParam: function(queryParams){ 231 var append = queryParams[1] || false; 232 this.queryParam = queryParams[0]; 233 if ((this.resultStore.getCount() == 0 && !this.resultStore.isFiltered()) || append) { 234 if (this.queryParam.worksetIdCriterion != null && !append) { 235 // loading a workset, so clear out the current one 236 this.resetWorkset(); 237 } 238 this.resultStore.baseParams = this.queryParam; 239 this.resultStore.proxy.conn.url = this.searchAndBrowseURL; 240 this.resultStore.on('load',function(store,records,options){ 241 Workbench.component.manager.notify(new Monk.event.chunk.ChunksSimilarRetrieved({ 242 label: 'search documents retrieved: ' 243 }), this.getDocumentList()); 244 },this, {single: true}); 245 this.resultStore.load({ 246 params: {start: 0,limit: 1000}, 247 add: append 248 }); 249 } else { 250 Workbench.console.info("filtering resultStore"); 251 this.resultStore.filterBy(function(record, id){ 252 var match = false; 253 for (var name in queryParams[0]) { 254 switch (name) { 255 case 'corpusCriterion': 256 if (record.data.collection.indexOf(queryParam[name]) != -1) match = true; 257 case 'authorName': 258 if (record.data.author.indexOf(queryParam[name]) != -1) match = true; 259 case 'authorGender': 260 if (record.data.authorGender.indexOf(queryParam[name]) != -1) match = true; 261 case 'authorStartBirthYear': 262 if (record.data.authorBirthYear >= queryParam[name]) match = true; 263 case 'authorStartDeathYear': 264 if (record.data.authorDeathYear >= queryParam[name]) match = true; 265 case 'authorEndBirthYear': 266 if (record.data.authorBirthYear <= queryParam[name]) match = true; 267 else match = false; 268 case 'authorEndDeathYear': 269 if (record.data.authorDeathYear <= queryParam[name]) match = true; 270 else match = false; 271 case 'titlePattern': 272 var pattern = new RegExp(queryParam[name], 'i'); 273 if (record.data.label.match(pattern) != null) match = true; 274 case 'genre': 275 if (record.data.genre.indexOf(queryParam[name]) != -1) match = true; 276 case 'circulationDateStart': 277 if (record.data.circulationStart >= queryParam[name]) match = true; 278 case 'circulationDateEnd': 279 if (record.data.circulationEnd <= queryParam[name]) match = true; 280 case 'workpartIdCriterion': 281 if (record.data.workpartIdCriterion == queryParam[name]) match = true; 282 } 283 } 284 return match; 285 }, this); 286 } 287 }, 288 289 doSimpleQuery: function(queryParam, append){ 290 append = append || false; 291 this.queryParam = queryParam; 292 if (this.resultStore.getCount() == 0 && !this.resultStore.isFiltered()) { 293 this.resultStore.baseParams = this.queryParam; 294 this.resultStore.proxy.conn.url = this.simpleSearchURL; 295 this.resultStore.on('load',function(store,records,options){ 296 Workbench.component.manager.notify(new Monk.event.chunk.ChunksSimilarRetrieved({ 297 label: 'search documents retrieved: ' 298 }), this.getDocumentList()); 299 },this, {single: true}); 300 this.resultStore.load({params: {start: 0,limit: 1000}, add: append}); 301 } else { 302 this.resultStore.filterBy(function(record, id){ 303 var match = false; 304 for (var name in record.data) { 305 var pattern = new RegExp(queryParam.featureValue, 'i'); 306 if (record.data[name].match(pattern) != null) { 307 match = true; 308 break; 309 } 310 } 311 return match; 312 }, this); 313 } 314 }, 315 /**This call allows all the containers -worksets/search criterion etc. 316 * the setSimilarQueryParam call is redundant 317 * 318 * @param {} queryParam 319 */ 320 doSimilarityQuery: function(queryParam, append){ 321 append = append || false; 322 this.queryParam = queryParam; 323 this.queryParam.format = "xml"; 324 Workbench.console.info("here in data manager -similar all query: "+ this.queryParam.feature); 325 this.resultStore.baseParams = this.queryParam; 326 this.resultStore.proxy.conn.url = this.similarityAllSearchURL; 327 this.resultStore.on('load',function(store,records,options){ 328 Workbench.component.manager.notify(new Monk.event.chunk.ChunksSimilarRetrieved({ 329 label: 'search documents retrieved: ' 330 }), this.getDocumentList()); 331 Workbench.console.info("===> retrieved the documents. In resultstore: " + this.resultStore.getCount()); 332 },this, {single: true}); 333 this.resultStore.load({params: {start: 0,limit: 1000, format: 'xml'}, add: append}); 334 }, 335 336 /** 337 * Set similar search query param 338 * @deprecated 339 */ 340 setSimilarQueryParam: function(queryParam, append){ 341 append = append || false; 342 this.queryParam = queryParam; 343 Workbench.console.info("here in data manager -similar query: "+ this.queryParam.feature); 344 this.resultStore.baseParams = this.queryParam; 345 this.resultStore.proxy.conn.url = this.similaritySearchURL; 346 this.resultStore.on('load',function(store,records,options){ 347 Workbench.component.manager.notify(new Monk.event.chunk.ChunksSimilarRetrieved({ 348 label: 'search documents retrieved: ' 349 }), this.getDocumentList()); 350 },this, {single: true}); 351 this.resultStore.load({params: {start: 0,limit: 1000, format: 'xml'}, add: append}); 352 }, 353 354 /**This query will retrieve the workset information from the 355 * middleware and update the common work store that is used by the 356 * result summary tool 357 * 358 */ 359 setWorksetQueryParam: function(id, append){ 360 append = append || false; 361 this.queryParam={'worksetId':id}; 362 Workbench.console.info("here in data manager -workset load query: "+ this.queryParam.id); 363 this.resultStore.baseParams = this.queryParam; 364 this.resultStore.proxy.conn.url = this.worksetSearchURL; 365 this.resultStore.on('load',function(store,records,options){ 366 Workbench.component.manager.notify(new Monk.event.chunk.ChunksSimilarRetrieved({ 367 label: 'workset documents retrieved: ' 368 }), this.getDocumentList()); 369 },this, {single: true}); 370 this.resultStore.load({params: {start: 0,limit: 1000, format: 'xml'}, add: append}); 371 }, 372 373 374 handle : function(monkEvent, data){ 375 if (monkEvent.instanceOf((Monk.event.analysis.GotSeasrAnalysisResults))) { 376 var instanceId = data.instanceId; 377 378 var jsonString = Monk.utils.xml2json(data.results, " "); 379 var json = ""; 380 (eval('json='+jsonString)); 381 382 if (json.results.result.length == null) { 383 json.results.result = [json.results.result]; // json array fix 384 } 385 386 // reset analysis values 387 this.setFeatureList([]); 388 this.setDecisionTree(""); 389 this.setDecisionTreeSummary(""); 390 391 var results = this.processResults(instanceId, json.results.result); 392 393 if (this.performingAnalysis) { 394 var conn = new Ext.data.Connection(); 395 conn.request({ 396 url: Monk.data.PROXY_URL + 'get/SeasrManager.getConfigParameters', 397 method: 'GET', 398 params: {instanceId: instanceId}, 399 success: function(responseObject) { 400 var result = responseObject.responseXML.getElementsByTagName('result')[0]; 401 if (result != null) { 402 var entries = result.getElementsByTagName('params'); 403 for (var i = 0, length = entries.length; i < length; i++) { 404 var entry = entries[i]; 405 var type = entry.getAttribute('name') 406 if (type == 'toolsetId') { 407 this.cachedData.toolsetId = entry.getElementsByTagName('value')[0].firstChild.data; 408 } 409 if (type == 'worksetId') { 410 this.cachedData.worksetId = entry.getElementsByTagName('value')[0].firstChild.data; 411 } 412 if (type == 'flowId') { 413 this.cachedData.itinerary = entry.getElementsByTagName('value')[0].firstChild.data; 414 } 415 if (type == 'resultDescription') { 416 this.cachedData.description = entry.getElementsByTagName('value')[0].firstChild.data; 417 } 418 if (type == 'resultName') { 419 this.cachedData.name = entry.getElementsByTagName('value')[0].firstChild.data; 420 } 421 } 422 } 423 424 // temp date 425 var date = new Date(); 426 var dateStarted = date.format('Y-m-d h:i:s'); 427 var dateEnded = dateStarted; 428 429 // copy values to the results 430 for (var i = 0, length = results.tempResults.length; i < length; i++) { 431 results.tempResults[i].dateEnded = dateEnded; 432 results.tempResults[i].dateStarted = dateStarted; 433 results.tempResults[i].description = this.cachedData.description; 434 results.tempResults[i].flowId = this.cachedData.itinerary; 435 results.tempResults[i].name = this.cachedData.name; 436 results.tempResults[i].toosletId = this.cachedData.toolsetId; 437 results.tempResults[i].userId = 'null'; 438 results.tempResults[i].worksetId = this.cachedData.worksetId; 439 } 440 441 // add result to project data 442 Monk.component.dataManager.getProjectData().results.add(instanceId, results.tempResults); 443 444 Ext.getCmp('runAnalysisProgressBar').reset(); 445 Ext.getCmp('runAnalysisProgressBar').updateProgress(1, 'Analysis complete'); 446 this.progressDialog.buttons[0].enable(); // show results button 447 this.progressDialog.buttons[2].disable(); // cancel button 448 449 Workbench.component.manager.notify( 450 new Monk.event.workset.AnalysisResultsProcessed( 451 {label: 'Analysis results processed: '+ this.getWorksetName()} 452 ), 453 {worksetId: this.getWorksetId(), instanceId: instanceId, results: results.resultsProcessed, performingAnalysis: this.performingAnalysis} 454 ); 455 this.performingAnalysis = false; 456 this.cachedData = null; 457 }, 458 failure: function(response, options) { 459 Ext.Msg.alert('Data Manager', 'Error trying to get config parameters for the analysis call.<br/><b>Error</b>: '+response.statusText); 460 }, 461 scope: this 462 }); 463 } else { 464 Workbench.component.manager.notify( 465 new Monk.event.workset.AnalysisResultsProcessed( 466 {label: 'Analysis results processed: '+ this.getWorksetName()} 467 ), 468 {worksetId: this.getWorksetId(), instanceId: instanceId, results: results.resultsProcessed, performingAnalysis: this.performingAnalysis} 469 ); 470 } 471 } else if (monkEvent.instanceOf(Monk.event.flowmanager.StepSelected)) { 472 if (data == 'toolstep-003' && !this.performingAnalysis && this.progressDialog != null) { 473 this.progressDialog.close(); 474 } 475 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunkChecked)) { 476 this.processChunk(data); 477 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunksChecked)) { 478 for (var i = 0; i < data.length; i++) { 479 this.processChunk(data[i]); 480 } 481 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetCreated)) { 482 // get the new workset ID and set it 483 var xml = data.response.responseXML; 484 var worksetId = xml.getElementsByTagName('workset')[0].getAttribute('id'); 485 this.worksetId = worksetId; 486 487 var workset = this.getWorkset(); 488 // add extra info for WorksetSelector 489 var todaysDate = new Date(); 490 todaysDate = todaysDate.format('Y-m-d G:i:s'); 491 workset.date = [{'#text':todaysDate}]; 492 workset.id = worksetId; 493 workset.label = workset.worksetName; 494 this.getProjectData().worksets.add(worksetId, workset); 495 496 if (this.performingAnalysis) { 497 this.runAnalysis(); 498 } 499 500 this.unsavedWorksetData = false; 501 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetSaved)) { 502 if (this.performingAnalysis) { 503 this.runAnalysis(); 504 } 505 this.updateProjectDataWorkset(); 506 507 this.unsavedWorksetData = false; 508 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetDeleted)) { 509 this.getProjectData().worksets.removeKey(data.worksetId); 510 511 // reset everything if the deleted workset matches the current one 512 if (this.getWorksetId() == data.worksetId) { 513 this.reset(); 514 } 515 } else if (monkEvent.instanceOf(Monk.event.workset.GotWorkpartLabels)) { 516 //debugger; 517 var json = Monk.utils.xml2json(data.response.responseXML, " "); 518 var labels = ""; 519 (eval('labels='+json)); 520 //debugger; 521 if (labels.nodes != null && labels.nodes.node!=null) { 522 var labelsArray = labels.nodes.node; 523 for (var i = 0, length = labelsArray.length; i < length; i++) { 524 var labelNode = labelsArray[i]; 525 526 if (this.worklist[labelNode.id] == null) { 527 } else { 528 this.worklist[labelNode.id].text = labelNode.label['#text']; 529 // this.worklist[labelNode.id].genre= labelNode.genre; 530 // this.worklist[labelNode.id].circulation_year= labelNode.circulation_year; 531 this.worklist[labelNode.id].corpus= labelNode.corpus; 532 } 533 } 534 } 535 this.lastWorksetLoadedTimestamp = new Date().getTime(); 536 Workbench.component.manager.notify( 537 new Monk.event.workset.WorksetLoaded({ 538 label: 'Workset loaded: ' + this.getWorksetName() 539 }), { 540 id: this.getWorksetId(), 541 timestamp : this.lastWorksetLoadedTimestamp 542 } 543 ); 544 545 this.unsavedWorksetData = false; 546 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunkSelected)) { 547 this.setCurrentChunk(data); 548 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunkRated)) { 549 // set the rating to the specified chunk 550 var chunkId = data.chunkId; 551 var rating = data.rating; 552 this.worklist[chunkId].userRating = rating; 553 554 this.unsavedWorksetData = true; 555 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunksRated)) { 556 for (var i=0;i<data.length;i++) { 557 this.worklist[data[i].id] = data[i]; 558 } 559 560 this.unsavedWorksetData = true; 561 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetReset)) { 562 this.reset(); 563 } else if (monkEvent.instanceOf(Monk.event.analysis.SeasrAnalysisRun)) { 564 this.updateProgress(data); 565 } else if (monkEvent.instanceOf(Monk.event.ServerError)) { 566 if (data.url != null) { 567 if (data.url.match(/SchedulerManager.runAnalysis/) != null) { 568 this.progressDialog.close(); 569 Monk.component.messenger.alert('Analysis Tool', '<b>There was an error getting the prediction:</b><br />'+data.error); 570 } 571 } 572 } else if (monkEvent.instanceOf(Monk.event.analysis.GotJobStatus)) { 573 this.processStatus(data); 574 }else if(monkEvent.instanceOf(Monk.event.chunk.ChunksSimilarRetrieved)){ 575 this.setChunkSimilar(data); 576 }else if(monkEvent.instanceOf(Monk.event.workbench.AdvancedSearchQuery)){ 577 this.setSearchQueryParam(data); 578 }else if(monkEvent.instanceOf(Monk.event.workbench.SimilarSearchQuery)){ 579 this.setSimilarQueryParam(data); 580 }else if(monkEvent.instanceOf(Monk.event.project.LoadSelectedWorkset)){ 581 this.setWorksetQueryParam(data); 582 }else if(monkEvent.instanceOf(Monk.event.chart.FeatureComparison)){ 583 this.doFeatureComparison(data.type,data.featureType,data.queryParam); 584 }else if(monkEvent.instanceOf(Monk.event.workbench.SimpleSearchQuery)){ 585 this.doSimpleQuery(data); 586 }else if(monkEvent.instanceOf(Monk.event.workbench.ClearSearch)){ 587 if (data.clearAll) { 588 this.resultStore.removeAll(); 589 } else { 590 this.resultStore.clearFilter(); 591 } 592 }else if(monkEvent.instanceOf( Monk.event.workbench.WorksetDocumentComparison)){ 593 if(data.method.toString()=="SimilarFeatures"){ 594 // do a similarity search here... 595 this.doSimilarityQuery(data); 596 }else if( data.method.toString()=="SimilarFeatures:swap"){ 597 this.doSimilarityQuery(data); 598 }else{ 599 Workbench.console.info("unsupported method: " + data.method +"=="+data.method.toString()); 600 } 601 } 602 }, 603 604 /** 605 * Returns list of chunks saved from the previous similarity/search browse 606 */ 607 getChunkSimilar: function(){ 608 return this.chunkList; 609 }, 610 611 /** 612 * Return the query parameter 613 */ 614 getQueryParam: function(){ 615 return this.queryParam; 616 }, 617 618 619 /** 620 * Store the list of chunks retrieved as a result of a search/browse 621 * or Similarity search 622 * @param {String array} 623 */ 624 setChunkSimilar: function(chunkList){ 625 this.chunkList=chunkList; 626 }, 627 628 629 /** 630 * Reset the chunkList 631 */ 632 resetChunkSimilar: function(){ 633 this.chunkSimilar=[]; 634 this.resultStore.removeAll(); 635 }, 636 637 resetQueryParam: function(){ 638 this.queryParam=null; 639 this.resultStore.removeAll(); 640 }, 641 642 /** 643 * Resets everything back to the initial values. 644 * @param {Boolean} resetProject True to reset the project as well. 645 */ 646 reset : function(resetProject) { 647 if (resetProject) { 648 this.projectId = null; 649 this.projectData = null; 650 this.toolsetId = null; 651 } 652 this.currentChunk = null; 653 this.instanceId = null; 654 this.chunkType = null; 655 this.resetWorkset(); 656 this.resetResults(); 657 this.resetChunkSimilar(); 658 this.resetQueryParam(); 659 this.resultStore.removeAll(); 660 }, 661 662 663 /** 664 * Returns the workset to its initial state 665 */ 666 resetWorkset : function() { 667 this.worksetId = null; 668 this.worklist = {}; 669 this.worksetName = null; 670 this.itinerary = ""; 671 this.feature = ""; 672 this.unsavedWorksetData = false; 673 this.resultStore.removeAll(); 674 }, 675 676 /** 677 * Returns the results to their initial state 678 */ 679 resetResults : function() { 680 this.featureList = []; 681 this.decisionTree = ""; 682 this.decisionTreeSummary = ""; 683 this.resultSummary = ""; 684 }, 685 686 /** 687 * Returns the project ID for this workset. 688 * @return {String} The project ID 689 */ 690 getProjectId : function() { 691 return this.projectId; 692 }, 693 694 /** 695 * Sets the project ID for this workset. 696 * @param {String} projectId The project ID 697 */ 698 setProjectId : function(projectId) { 699 this.projectId = projectId; 700 }, 701 702 /** 703 * Returns the workset ID for this workset. 704 * @return {String} The workset ID 705 */ 706 getWorksetId : function() { 707 return this.worksetId; 708 }, 709 710 /** 711 * Sets the workset ID for this workset. 712 * @param {String} worksetId The workset ID 713 */ 714 setWorksetId : function(worksetId) { 715 this.worksetId = worksetId; 716 }, 717 718 /** 719 * Returns the workset label (longer form) for this workset. 720 * @return {String} The workset label 721 */ 722 getWorksetLabel : function() { 723 return "Workset: "+ (this.worksetName ? this.worksetName + " (id: " + this.worksetId + ")" : "[undetermined]"); 724 }, 725 726 /** 727 * Returns true if there is unsaved workset data. 728 * @return {Boolean} Is there unsaved workset data. 729 */ 730 isWorksetUnsaved : function() { 731 return this.unsavedWorksetData; 732 }, 733 734 /** 735 * Returns the timestamp from the last load of workset 736 * @return {Number} The last timestamp 737 */ 738 getLastWorksetLoadedTimestamp : function() { 739 return this.lastWorksetLoadedTimestamp; 740 }, 741 742 /** 743 * Returns the toolset ID for this toolset. 744 * @return {String} The toolset ID 745 */ 746 getToolsetId : function() { 747 return this.toolsetId; 748 }, 749 750 /** 751 * Sets the toolset ID for this toolset. 752 * @param {String} toolsetId The toolset ID 753 */ 754 setToolsetId : function(toolsetId) { 755 this.toolsetId = toolsetId; 756 }, 757 758 /** 759 * Returns the instance ID for the most recent analysis result. 760 * @return {String} The instance ID 761 */ 762 getInstanceId : function() { 763 return this.instanceId; 764 }, 765 766 /** 767 * Sets the instance ID for the most recent analysis result. 768 * @param {String} instanceId The instance ID 769 */ 770 setInstanceId : function(instanceId) { 771 this.instanceId = instanceId; 772 }, 773 774 /** 775 * This is a legacy method to adapt to the Nora services. 776 * It tallies up the chunkTypes and sets the workset's chunkType 777 * to whichever is the most prevalent. 778 * @return {String} The chunk type 779 */ 780 getChunkType : function() { 781 // TODO: chunkType will eventually be set on a per chunk basis. 782 // var chunkTypeArray = []; 783 // for (var chunkId in this.worklist) { 784 // var chunkType = this.worklist[chunkId].chunkType; 785 // if (chunkTypeArray.length == 0) { 786 // chunkTypeArray.push([chunkType]); 787 // } else { 788 // var chunkAdded = false; 789 // for (var i = 0; i < chunkTypeArray.length; i++) { 790 // var type = chunkTypeArray[i][0]; 791 // if (chunkType == type) { 792 // chunkTypeArray[i].push(chunkType); 793 // chunkAdded = true; 794 // } 795 // } 796 // if (!chunkAdded) { 797 // chunkTypeArray.push([chunkType]); 798 // } 799 // } 800 // } 801 // 802 // chunkTypeArray.sort(function(a, b) { 803 // if (a.length > b.length) return -1; 804 // if (a.length < b.length) return 1; 805 // return 0; 806 // }); 807 // 808 // this.chunkType = chunkTypeArray[0][0]; 809 810 this.chunkType = 'work'; 811 812 return this.chunkType; 813 }, 814 815 /** 816 * Returns the chunk currently being viewed. 817 * @returns {Object} The current chunk. 818 */ 819 getCurrentChunk : function() { 820 return this.currentChunk; 821 }, 822 823 /** 824 * Sets the chunk currently being viewed. 825 * @params {Object} chunk The chunk object. 826 * @params {String} chunk.id The id of the chunk. 827 * @params {String} chunk.corpus The corpus that the chunk belongs to. 828 * @params {String} chunk.text The label of the chunk. 829 */ 830 setCurrentChunk : function(chunk) { 831 this.currentChunk = chunk; 832 }, 833 834 /** 835 * Returns the worklist for this workset. 836 * @return {Object} The worklist 837 */ 838 getWorklist : function() { 839 return this.worklist; 840 }, 841 842 /** 843 * Sets the worklist for this workset. 844 * It accepts 3 arrays (chunk IDs, system ratings, and rating confidence) whose items should have a 1 to 1 relation 845 * and be in the same order. 846 * @param {Array} worklist The chunk IDs 847 * @param {Array} [worklistRating] The ratings for each chunk 848 * @param {Array} [confidence] The confidence for each predicted rating 849 */ 850 setWorklist : function(worklistArray, worklistRatingArray, confidenceArray) { 851 worklistRatingArray = worklistRatingArray || []; 852 confidenceArray = confidenceArray || []; 853 for (var i = 0; i < worklistArray.length; i++) { 854 var chunkId = worklistArray[i]; 855 var rating = worklistRatingArray[i]; 856 var confidence = confidenceArray[i]; 857 if (this.worklist[chunkId] == null) { 858 this.worklist[chunkId] = (rating != null) ? {systemRating: rating} : {}; 859 } else { 860 if (rating != null) this.worklist[chunkId].systemRating = rating; 861 } 862 if (confidence != null) this.worklist[chunkId].confidence = confidence; 863 } 864 }, 865 866 /** 867 * Clears the worklist for the current workset. 868 */ 869 clearWorklist : function() { 870 this.worklist = {}; 871 }, 872 873 /** 874 * Sets the training list for this workset. 875 * It accepts 2 comma-separated strings (chunk IDs and user ratings) whose items should have a 1 to 1 relation 876 * and be in the same order. 877 * Currently we're storing trainingList values in the worklist as userRating property 878 * @param {String} trainingList The chunk IDs 879 * @param {String} trainingListRating The ratings for each chunk 880 */ 881 setUserRatings : function(trainingList, trainingListRating) { 882 var trainingListArray = trainingList.split(','); 883 if(trainingListRating!=null){ 884 var trainingListRatingArray = trainingListRating.split(','); 885 for (var i = 0; i < trainingListArray.length; i++) { 886 if (trainingListArray[i] != 'null') { 887 var chunkId = trainingListArray[i]; 888 var rating = trainingListRatingArray[i]; 889 if (this.worklist[chunkId] == null) { 890 this.worklist[chunkId] = (rating != 'null') ? {userRating: rating} : {}; 891 } else { 892 if (rating != 'null') this.worklist[chunkId].userRating = rating; 893 } 894 } 895 }//end of for 896 }else{ 897 //trainingListRating==null 898 for (var i = 0; i < trainingListArray.length; i++) { 899 900 var chunkId = trainingListArray[i]; 901 var rating = "Training set" 902 if (this.worklist[chunkId] == null) { 903 this.worklist[chunkId] = (rating != 'null') ? {userRating: rating} : {}; 904 } else { 905 if (rating != 'null') this.worklist[chunkId].userRating = rating; 906 } 907 908 }//end of for 909 910 } 911 }, 912 913 /** 914 * Returns the feature list. 915 * @return {Array} The feature list 916 */ 917 getFeatureList : function() { 918 return this.featureList; 919 }, 920 921 /** 922 * Set the feature list for this workset. 923 * @param {Array} featureList An array of features 924 */ 925 setFeatureList : function(featureList) { 926 this.featureList = featureList; 927 }, 928 929 /** 930 * Returns the decision tree 931 * @return {String} The decision tree 932 */ 933 getDecisionTree : function() { 934 return this.decisionTree; 935 }, 936 937 /** 938 * Set the decision tree summary. 939 * @param {String} decisionTree A decision tree string 940 */ 941 getDecisionTreeImage : function() { 942 return this.decisionTreeImage; 943 }, 944 945 /** 946 * Set the decision tree summary. 947 * @param {String} decisionTree A decision tree string 948 */ 949 setDecisionTreeImage : function(decisionTreeImage) { 950 this.decisionTreeImage = decisionTreeImage; 951 }, 952 953 954 /** 955 * Set the decision tree. 956 * @param {String} decisionTree A decision tree string 957 */ 958 setDecisionTree : function(decisionTree) { 959 this.decisionTree = decisionTree; 960 }, 961 962 /** 963 * Returns the decision tree summary 964 * @return {String} The decision tree 965 */ 966 getDecisionTreeSummary : function() { 967 return this.decisionTreeSummary; 968 }, 969 970 /** 971 * Set the decision tree summary. 972 * @param {String} decisionTree A decision tree string 973 */ 974 setDecisionTreeSummary : function(decisionTreeSummary) { 975 this.decisionTreeSummary = decisionTreeSummary; 976 }, 977 978 /** 979 * Returns the name of this workset. 980 * @return {String} The workset name 981 */ 982 getWorksetName : function() { 983 return this.worksetName; 984 }, 985 986 /** 987 * Sets the name of this workset. 988 * @param {String} worksetName The name of the workset 989 */ 990 setWorksetName : function(worksetName) { 991 this.worksetName = worksetName; 992 }, 993 994 /** 995 * Returns the itinerary for this workset. 996 * @return {String} The itinerary 997 */ 998 getItinerary : function() { 999 return this.itinerary; 1000 }, 1001 1002 /** 1003 * Sets the itinerary for this workset. 1004 * Possible values are: 'MonkNaiveBayes', and 'MonkDTree'. 1005 * @param {String} itinerary The itinerary 1006 */ 1007 setItinerary : function(itinerary) { 1008 this.itinerary = itinerary; 1009 }, 1010 1011 /** 1012 * Returns the feature for this workset. 1013 * @return {String} The feature 1014 */ 1015 getFeature : function() { 1016 return this.feature; 1017 }, 1018 1019 /** 1020 * Sets the feature for this workset. 1021 * Possible values are: 'contents', 'twogram_contents' and 'threegram_contents'. 1022 * @param {String} feature The feature 1023 */ 1024 setFeature : function(feature) { 1025 this.feature = feature; 1026 }, 1027 1028 /** 1029 * Returns the terms/features found in a specific chunk. 1030 * @param {String} chunkId The chunk ID 1031 * @return {Array} An array of terms 1032 */ 1033 getTermsForChunk : function(chunkId) { 1034 var chunk = this.getWorklist()[chunkId]; 1035 if (chunk != null) { 1036 return chunk.terms; 1037 } else { 1038 return null; 1039 } 1040 }, 1041 1042 /** 1043 * Associates a number of terms/features with a specific chunk. 1044 * @param {String} chunkId The chunk ID 1045 * @param {Array} terms An array of terms to add 1046 */ 1047 addTermsToChunk : function(chunkId, terms) { 1048 if (this.getTermsForChunk(chunkId) == null) { 1049 this.getWorklist()[chunkId].terms = terms; 1050 } else { 1051 for (var i = 0; i < terms.length; i++) { 1052 var term = terms[i]; 1053 if (this.getWorklist()[chunkId].terms.indexOf(term) == -1) { 1054 this.getWorklist()[chunkId].terms.push(term); 1055 } 1056 } 1057 } 1058 }, 1059 1060 /** 1061 * Removes the terms/features associated with a specific chunk. 1062 */ 1063 clearTermsForChunks : function() { 1064 var worklist = this.getWorklist(); 1065 for (chunkId in worklist) { 1066 delete worklist[chunkId].terms; 1067 } 1068 }, 1069 1070 /** 1071 * Returns the current workset, including all the relevant properties. 1072 * Currently some properties are being adapted for use with Nora services: 1073 * e.g. chunk user ratings are returned as the trainingListArray/trainingListRatingArray 1074 * @return {Object} The workset object 1075 */ 1076 getWorkset : function() { 1077 // here we're making changes to adapt the workset for using old Nora services 1078 1079 var worklist = this.getWorklist(); 1080 var chunkType = this.getChunkType(); 1081 var worklistArray = []; 1082 var worklistRatingArray = []; 1083 var trainingListArray = []; 1084 var trainingListRatingArray = []; 1085 1086 for (var chunkId in worklist) { 1087 var chunk = worklist[chunkId]; 1088 1089 worklistArray.push(chunkId); 1090 if (chunk.systemRating) { 1091 worklistRatingArray.push(chunk.systemRating); 1092 } 1093 1094 1095 if (chunk.userRating){ 1096 trainingListArray.push(chunkId); 1097 trainingListRatingArray.push(chunk.userRating); 1098 } 1099 } 1100 1101 var workset = { 1102 projectId: this.getProjectId(), 1103 worksetId: this.getWorksetId(), 1104 chunkType: chunkType, 1105 itinerary: this.getItinerary(), 1106 worksetName: this.getWorksetName(), 1107 feature: this.getFeature(), 1108 trainingList: trainingListArray.join(), 1109 trainingListRating: trainingListRatingArray.join(), 1110 workList: worklistArray.join(), 1111 workListRating: worklistRatingArray.join() 1112 }; 1113 return workset; 1114 }, 1115 1116 /** 1117 * Loads a workset into the data manager. Then gets the labels from the server. 1118 * @param {Object} workset 1119 * @config {String} label 1120 * @config {Integer} id 1121 * @config {Integer} projectId 1122 * @config {String} trainingList 1123 * @config {String} trainingListRating 1124 * @config {String} workList 1125 * @config {String} workListRating 1126 * @config {String} itinerary 1127 */ 1128 setWorkset : function(workset) { 1129 this.resetWorkset(); 1130 1131 if (workset.label) this.setWorksetName(workset.label); 1132 if (workset.projectId) this.setProjectId(workset.projectId); 1133 if (workset.id) this.setWorksetId(workset.id); 1134 if (workset.feature) this.setFeature(workset.feature); 1135 if (workset.trainingList) this.setUserRatings(workset.trainingList, workset.trainingListRating); 1136 // ignore worklistRating here, only set it from processResults method below 1137 if (workset.workList) this.setWorklist(workset.workList.split(','), null); 1138 if (workset.itinerary) this.setItinerary(workset.itinerary); 1139 1140 for (var nodeId in this.worklist) { 1141 this.worklist[nodeId].chunkType = 'work'; 1142 } 1143 1144 Monk.data.workset.getWorkpartLabels(workset.id, 'worklist'); 1145 }, 1146 1147 1148 /** 1149 * Checks for a minimum of 2 ratings in the workset, (before running an analysis). 1150 * @returns {Boolean} True if the workset is valid. 1151 */ 1152 isWorksetValid : function () { 1153 var ratings = {}; 1154 var tlr = this.getWorkset().trainingListRating.split(','); 1155 for (var i=0;i<tlr.length;i++) { 1156 if (tlr[i]) { 1157 if (!ratings[tlr[i]]) {ratings[tlr[i]]=0} 1158 ratings[tlr[i]]++; 1159 } 1160 } 1161 var ks = 0; 1162 for (var r in ratings) { 1163 ks++; 1164 } 1165 if (ks<2) { 1166 return false; 1167 } 1168 return true; 1169 }, 1170 1171 /** 1172 * @return {Object} The data associated with the project for this session 1173 * @config {String} created 1174 * @config {String} label 1175 * @config {Integer} projectId 1176 * @config {Object} toolsets 1177 * @config {Object} worksets 1178 */ 1179 getProjectData : function() { 1180 return this.projectData; 1181 }, 1182 1183 /** 1184 * Set the project data for this session 1185 * @param {Object} projectData 1186 * @config {String} created 1187 * @config {String} label 1188 * @config {Integer} projectId 1189 * @config {Object} toolsets 1190 * @config {Object} worksets 1191 */ 1192 setProjectData : function(projectData) { 1193 this.projectData = projectData; 1194 }, 1195 1196 /** 1197 * Update the workset in projectData with the values from the currently loaded workset. 1198 */ 1199 updateProjectDataWorkset : function() { 1200 var newWorkset = this.getWorkset(); 1201 var oldWorkset = this.getProjectData().worksets.get(newWorkset.worksetId); 1202 for (var property in oldWorkset) { 1203 var newProperty = newWorkset[property]; 1204 if (newProperty != null) oldWorkset[property] = newProperty; 1205 } 1206 this.getProjectData().worksets.replace(newWorkset.worksetId, oldWorkset); 1207 }, 1208 1209 /** 1210 * Returns the result summary. 1211 * @return {String} The result summary 1212 */ 1213 getResultSummary : function() { 1214 return this.resultSummary; 1215 }, 1216 1217 /** 1218 * Set the result summary. 1219 * @param {String} A string describing the result. 1220 */ 1221 setResultSummary : function(result) { 1222 this.resultSummary = result; 1223 }, 1224 1225 /** 1226 * Gets results of a particular type. 1227 * @param {String} type Can be either: 'feature', 'tree', 'prediction' 1228 * @return {Array} The filtered results 1229 */ 1230 getResults : function(type) { 1231 var filteredResults = []; 1232 var results = Monk.component.dataManager.getProjectData().results; 1233 var filter = ""; 1234 1235 switch (type) { 1236 case 'feature': 1237 filter = 'org.monkproject.meandre.components.beans.features.FeatureList'; 1238 break; 1239 case 'tree': 1240 filter = 'org.monkproject.meandre.components.beans.C45TreeBean'; 1241 break; 1242 case 'prediction': 1243 filter = 'org.monkproject.meandre.components.beans.PredictionFlowResult'; 1244 break; 1245 default: 1246 throw "wrong type"; 1247 } 1248 1249 for (var i = 0, length = results.length; i < length; i++) { 1250 var result = results[i]; 1251 if (results.dataType == filter) { 1252 filteredResults.push(result); 1253 } 1254 } 1255 1256 return filteredResults; 1257 }, 1258 1259 /** 1260 * Takes an associative array and returns two arrays: keys and values. 1261 * If innerValue is passed, then the method looks for a property of value 1262 * instead of the value itself e.g. value = object[key][innerValue]. 1263 * @param {Object} associativeArray 1264 * @param {String} innerValue 1265 * @return {Array} An array containing two arrays of keys and values 1266 */ 1267 associativeArray2Arrays : function(associativeArray, innerValue) { 1268 var keys = ""; 1269 var values = ""; 1270 if (associativeArray == null) { 1271 keys = null; 1272 values = null; 1273 } else { 1274 for (var key in associativeArray) { 1275 keys += key + ','; 1276 if (innerValue != null) { 1277 values += associativeArray[key][innerValue] + ','; 1278 } else { 1279 values += associativeArray[key] + ','; 1280 } 1281 } 1282 keys = keys.substr(0, keys.length - 1); // trim last comma 1283 values = values.substr(0, values.length - 1); 1284 } 1285 return [keys, values]; 1286 }, 1287 1288 1289 /** 1290 * Helper methods used primarily by ProjectSelector and feature.initializeParameters. 1291 */ 1292 1293 /** 1294 * Creates a new project object, suitable for addition to projectData. 1295 * @param {Element} projectElement An element containing project info. 1296 * @return {Object} A project object 1297 */ 1298 createNewProject : function(projectElement) { 1299 if (projectElement==undefined) { 1300 Ext.Msg.show({ 1301 title:'Project Error', 1302 msg: 'An attempt was made to load an inexistent project. Continuing will likely cause further errors. Would you like to start over at the welcome screen?', 1303 buttons: Ext.Msg.OKCANCEL, 1304 fn: function(btnId) { 1305 if (btnId == 'ok') { 1306 document.location = document.location.pathname; 1307 } 1308 }, 1309 icon: Ext.MessageBox.ERROR 1310 }) 1311 } 1312 var label = projectElement.getElementsByTagName('label')[0].firstChild.data; 1313 var commentsElement = projectElement.getElementsByTagName('comments')[0]; 1314 var comments = null; 1315 if (commentsElement) { 1316 if (commentsElement.firstChild != null) comments = commentsElement.firstChild.data; 1317 } 1318 var created = projectElement.getElementsByTagName('datecreated')[0].firstChild.data; 1319 var projectId = projectElement.getAttribute('id'); 1320 projectData = { 1321 projectId: projectId, created: created, label: label, comments: comments, 1322 worksets: new Ext.util.MixedCollection(), 1323 toolsets: new Ext.util.MixedCollection(), 1324 results: new Ext.util.MixedCollection() 1325 }; 1326 1327 return projectData; 1328 }, 1329 1330 /** 1331 * Adds results to the project data. 1332 * @param {Element} resultsElement An element containing results info. 1333 * @param {Object} projectData The project data to add to. 1334 */ 1335 addResultsToProject : function(resultsElement, projectData) { 1336 if (resultsElement.getAttribute('num') != null) { 1337 var jsonString = Monk.utils.xml2json(resultsElement, " "); 1338 var json = ""; 1339 (eval('json='+jsonString)); 1340 1341 if (json.results.result.length == null) { 1342 json.results.result = [json.results.result]; // json array fix 1343 } 1344 1345 for (var i = 0, length = json.results.result.length; i < length; i++) { 1346 var result = json.results.result[i]; 1347 1348 var instanceId = result.instanceId ? result.instanceId : json.results.instanceId; 1349 var sameInstance = projectData.results.get(instanceId); 1350 if (sameInstance == null) { 1351 projectData.results.add(instanceId, [result]); 1352 } else { 1353 var addedValue = false; 1354 for (var j = 0, length2 = sameInstance.length; j < length2; j++) { 1355 var oldResult = sameInstance[j]; 1356 if (oldResult.value == null) { 1357 if (oldResult.dataType == result.dataType) { 1358 oldResult.value = result.value; 1359 addedValue = true; 1360 } 1361 } 1362 } 1363 if (!addedValue) sameInstance.push(result); 1364 } 1365 } 1366 } 1367 }, 1368 1369 /** 1370 * Processes results data and sets it in this DataManager. 1371 * @param {String} instanceId The instance ID for the analysis which produced these results. 1372 * @param {Array} resultsArray The array of results to process. 1373 * @return {Object} 1374 * @config {Array} tempResults An array of processed temp results (for saving later). 1375 * @config {String} resultsProcessed A string describing the types of results processed. 1376 */ 1377 processResults : function(instanceId, resultsArray) { 1378 var resultsInfo = {tempResults: [], resultsProcessed: []}; 1379 1380 for (var i = 0; i < resultsArray.length; i++) { 1381 var result = resultsArray[i]; 1382 1383 var dataType = result.dataType; 1384 if (dataType == "org.monkproject.meandre.components.beans.PredictionFlowResult") { 1385 var worklist = []; 1386 var worklistRating = []; 1387 var confidence = []; 1388 var predictionArray = result.value.PredictionFlowResult.result["org.monkproject.meandre.components.beans.PredictionResult"]; 1389 for (var j = 0; j < predictionArray.length; j++) { 1390 var prediction = predictionArray[j]; 1391 worklist.push(prediction.docId); 1392 worklistRating.push(prediction.value); 1393 confidence.push(prediction.probabilityRatio['double']); 1394 } 1395 1396 this.setWorklist(worklist, worklistRating, confidence); 1397 1398 var traininglist = []; 1399 var traininglistRating = []; 1400 //debugger; 1401 var trainingArray = result.value.PredictionFlowResult.trainingList.entry; 1402 1403 for (var j = 0; j < trainingArray.length; j++) { 1404 var training = trainingArray[j].string; 1405 traininglist.push(training[0]); 1406 traininglistRating.push(training[1]); 1407 } 1408 this.setUserRatings(traininglist.join(), traininglistRating.join()); 1409 1410 var summary = result.value.PredictionFlowResult.resultSummary; 1411 if (summary != null) { 1412 this.setResultSummary(summary); 1413 } 1414 1415 var tempResult = { 1416 dataType: dataType, 1417 instanceId: instanceId, 1418 value: result.value 1419 }; 1420 resultsInfo.tempResults.push(tempResult); 1421 resultsInfo.resultsProcessed.push('predictions'); 1422 } else if (dataType == "org.monkproject.meandre.components.beans.features.FeatureList") { 1423 var featureType = result.value.FeatureList.featureType; 1424 this.setFeature(featureType); 1425 1426 var features = result.value.FeatureList.feature["org.monkproject.meandre.components.beans.features.Feature"]; 1427 this.setFeatureList(features); 1428 1429 var tempResult = { 1430 dataType: dataType, 1431 instanceId: instanceId, 1432 value: result.value 1433 }; 1434 resultsInfo.tempResults.push(tempResult); 1435 resultsInfo.resultsProcessed.push('features'); 1436 } else if (dataType == "java.lang.String") { 1437 var treeString = escape(result.value.String); 1438 this.setDecisionTree(treeString); 1439 1440 var tempResult = { 1441 dataType: dataType, 1442 instanceId: instanceId, 1443 value: result.value 1444 }; 1445 resultsInfo.tempResults.push(tempResult); 1446 resultsInfo.resultsProcessed.push('decision tree'); 1447 } else if (dataType == "org.monkproject.meandre.components.beans.C45TreeBean") { 1448 //debugger; 1449 var treeSummary = result.value.C45TreeBean.resultSummary; 1450 var treeString = escape(result.value.C45TreeBean.tree); 1451 var treeImage = result.image; 1452 this.setDecisionTreeSummary(treeSummary); 1453 this.setDecisionTree(treeString); 1454 this.setDecisionTreeImage(treeImage); 1455 1456 var tempResult = { 1457 dataType: dataType, 1458 instanceId: instanceId, 1459 value: result.value 1460 }; 1461 resultsInfo.tempResults.push(tempResult); 1462 resultsInfo.resultsProcessed.push('decision tree summary'); 1463 1464 }else { 1465 } 1466 } 1467 1468 return resultsInfo; 1469 }, 1470 1471 /** 1472 * Creates a new toolset config object. 1473 * @param {String} toolsetId The toolset ID to use 1474 */ 1475 createToolsetConfig : function(toolsetId) { 1476 var config = {}; 1477 var toolset = this.getProjectData().toolsets.get(toolsetId); 1478 if (toolset == null) { 1479 // is it a default toolset? 1480 toolset = feature.toolsets.get(toolsetId); 1481 1482 if (toolset == undefined) { // bad toolset id given? 1483 Ext.Msg.show({ 1484 title:'Toolset Error', 1485 msg: 'An attempt was made to load an inexistent toolset. Continuing will likely cause further errors. Would you like to start over at the welcome screen?', 1486 buttons: Ext.Msg.OKCANCEL, 1487 fn: function(btnId) { 1488 if (btnId == 'ok') { 1489 document.location = document.location.pathname; 1490 } 1491 }, 1492 icon: Ext.MessageBox.ERROR 1493 }) 1494 } 1495 } 1496 config.id = toolset.id; 1497 config.label = toolset.label; 1498 config.pathToIcon = toolset.pathToIcon; 1499 config.shareable = toolset.shareable; 1500 config.description = toolset.description; 1501 config.worksetId = toolset.worksetId; // will be null if the toolset is a default 1502 1503 // convert the tools array into a MixedCollection 1504 config.tools = new Ext.util.MixedCollection(); 1505 for (var i = 0; i < toolset.tools.length; i++) { 1506 var tool = toolset.tools[i]; 1507 var processedTool = { 1508 id: tool.id, 1509 label: tool.label, 1510 components: tool.components, 1511 layouts: tool.layouts, 1512 helpUrl: tool.helpUrl 1513 }; 1514 config.tools.add(tool.id, processedTool); 1515 } 1516 1517 return config; 1518 }, 1519 1520 /** 1521 * Methods for running analyses 1522 */ 1523 initializeProgressDialog : function(cachedData) { 1524 this.performingAnalysis = true; 1525 this.cachedData = cachedData; 1526 1527 this.progressDialog = new Ext.Window({ 1528 title: 'Analysis Tool', 1529 height: 90, 1530 width: 300, 1531 modal: false, 1532 shadow: true, 1533 plain: true, 1534 border: false, 1535 collapsible: true, 1536 closable: true, 1537 layout: 'fit', 1538 items: { 1539 xtype: 'panel', 1540 items: { 1541 xtype: 'progress', 1542 id: 'runAnalysisProgressBar' 1543 } 1544 }, 1545 buttons: [{ 1546 text: 'Show Results', 1547 disabled: true, 1548 handler: function() { 1549 var lastStep = null; 1550 if (cachedData.toolsetId != feature.toolFlowManager.toolset.id) { 1551 // TODO doesn't work yet 1552 var toolsetConfig = Monk.component.dataManager.createToolsetConfig(cachedData.toolsetId); 1553 var toolsetObject = new Monk.component.Toolset(toolsetConfig); 1554 lastStep = toolsetObject.tools.last().id; 1555 1556 Monk.component.dataManager.setToolsetId(toolsetObject.id); 1557 feature.toolFlowManager.setToolset(toolsetObject); 1558 1559 if (feature.flowManager.currentStep != 'tool-flow-manager') { 1560 feature.flowManager.addStep(feature.toolFlowManager, false); 1561 } 1562 feature.flowManager.goToStep(feature.toolFlowManager.id, true); 1563 } else { 1564 var tools = feature.toolFlowManager.getToolsetTools(); 1565 lastStep = tools[tools.length - 2].id; 1566 if (feature.flowManager.currentStep != 'tool-flow-manager') { 1567 feature.flowManager.goToStep(feature.toolFlowManager.id, true); 1568 } 1569 } 1570 var deferredStep = function(lastStep) { 1571 feature.toolFlowManager.getStep(lastStep); 1572 } 1573 deferredStep.defer(50, this, [lastStep]); 1574 this.progressDialog.close(); 1575 }, 1576 scope: this 1577 },{ 1578 text: 'Show Log', 1579 handler: function() { 1580 var conn = new Ext.data.Connection(); 1581 conn.request({ 1582 url: Monk.data.PROXY_URL + 'get/SchedulerManager.log', 1583 method: 'GET', 1584 params: {token : Monk.component.dataManager.token}, 1585 success: function(responseObject) { 1586 var log = responseObject.responseText; 1587 log = log.replace(/</g, '<'); 1588 log = log.replace(/>/g, '>'); 1589 log = log.replace(/\s{2,10}/g, '<br/>'); 1590 var oldWindow = Ext.getCmp('logWindow'); 1591 if (oldWindow != null) oldWindow.close(); 1592 var logWindow = new Ext.Window({ 1593 id: 'logWindow', 1594 title: 'Analysis Log', 1595 height: 400, 1596 width: 400, 1597 modal: false, 1598 shadow: true, 1599 plain: true, 1600 border: false, 1601 collapsible: false, 1602 closable: true, 1603 layout: 'fit', 1604 items: { 1605 xtype: 'panel', 1606 html: '<div style="overflow: auto; height: 100%; width: 100%;">'+log+'</div>' 1607 } 1608 }); 1609 logWindow.show(); 1610 }, 1611 failure: function(response, options) { 1612 Ext.Msg.alert('Analysis Tool', 'Error getting log.<br/><b>Error</b>: '+response.statusText); 1613 }, 1614 scope: this 1615 }); 1616 }, 1617 scope: this 1618 },{ 1619 text: 'Cancel', 1620 handler: function(button) { 1621 // TODO check to see if we're already running the analysis (we could be saving the workset) 1622 button.disable(); 1623 this.performingAnalysis = false; 1624 Ext.getCmp('runAnalysisProgressBar').updateText('Aborting analysis...'); 1625 // TODO abort call sent twice as a temp fix 1626 Monk.data.seasr.abort(this.token); 1627 Monk.data.seasr.abort.defer(10, this, [this.token]); 1628 }, 1629 scope: this 1630 }], 1631 listeners: { 1632 hide: { 1633 fn: function() { 1634 this.cancelAnalysis(); 1635 }, scope: this 1636 } 1637 } 1638 }); 1639 this.progressDialog.show(); 1640 Ext.getCmp('runAnalysisProgressBar').wait(); 1641 Ext.getCmp('runAnalysisProgressBar').updateText('Saving workset...'); 1642 }, 1643 1644 runAnalysis : function() { 1645 Ext.getCmp('runAnalysisProgressBar').updateText('Contacting server...'); 1646 var flowId = Monk.component.dataManager.getItinerary(); 1647 var projectId = Monk.component.dataManager.getProjectId(); 1648 var worksetId = Monk.component.dataManager.getWorksetId(); 1649 var toolsetId = Monk.component.dataManager.getToolsetId(); 1650 var featureValue = Monk.component.dataManager.getFeature(); 1651 Monk.data.seasr.runAnalysis({ 1652 projectId: projectId, 1653 worksetId: worksetId, 1654 flowId: flowId, 1655 resultName: this.cachedData.name, 1656 resultDescription: this.cachedData.description, 1657 emailAddress: this.cachedData.email, 1658 feature: featureValue, 1659 majorWordClasses: this.cachedData.wordClass, 1660 cutoff: this.cachedData.numfeature, 1661 toolsetId: toolsetId, 1662 share: this.cachedData.share, 1663 async: this.cachedData.async 1664 }); 1665 }, 1666 1667 updateProgress : function(data) { 1668 if (this.performingAnalysis) { 1669 if (this.cachedData.async == false) { 1670 Ext.getCmp('runAnalysisProgressBar').updateText('Running analysis...'); 1671 this.token = data.token; 1672 this.setTimer(this.token); 1673 } else if (this.cachedData.async == true) { 1674 this.token = data.token; 1675 this.progressDialog.close(); 1676 Monk.component.messenger.alert('Analysis Tool', 'The server is analyzing your workset. You will receive an email upon completion.'); 1677 //this.getFeaturesButton.enable(); 1678 } 1679 } 1680 }, 1681 1682 processStatus : function(data) { 1683 this.instanceId = data.instanceId; 1684 if (data.status == 'FINISH') { 1685 this.jobStatusTimer.stop(); 1686 Ext.getCmp('runAnalysisProgressBar').updateText('Getting results...'); 1687 Monk.data.seasr.getAnalysisResults(this.instanceId, true); 1688 } else if (data.status == 'ABORT') { 1689 if (this.performingAnalysis) { 1690 // server error 1691 Monk.component.messenger.alert('Analysis Tool','An error happened at the analytics server. Close this window and click on Show Log to see the error message.'); 1692 Workbench.component.manager.notify(new Monk.event.analysis.Aborted({ 1693 label: 'Analysis aborted for token ' + this.token + ' Click on Show Log to display the log message' 1694 }), {status: data.status}); 1695 } else { 1696 // user aborted 1697 Monk.component.messenger.alert('Analysis Tool','Analysis call has been aborted.'); 1698 } 1699 this.cancelAnalysis(); 1700 } else if (data.status == 'ENQUEUED') { 1701 Ext.getCmp('runAnalysisProgressBar').updateText('In queue. Your position is: '+data.queuePos); 1702 } 1703 }, 1704 1705 setTimer : function(token) { 1706 // complicated timer object to preserve scope with setInterval 1707 function StatusRequester(token, time) { 1708 this.ref = null; 1709 this.time = time; 1710 this.token = token; 1711 } 1712 StatusRequester.prototype = { 1713 // TODO getAnalysisResults is getting called twice 1714 getIntervalFn: function(token) { 1715 return function() { 1716 Monk.data.seasr.getStatus(token); 1717 } 1718 }, 1719 start: function() { 1720 this.ref = setInterval(this.getIntervalFn(this.token), this.time); 1721 }, 1722 stop: function() { 1723 clearInterval(this.ref); 1724 } 1725 }; 1726 this.jobStatusTimer = new StatusRequester(token, this.timerInterval); 1727 this.jobStatusTimer.start(); 1728 }, 1729 1730 cancelAnalysis : function() { 1731 this.performingAnalysis = false; 1732 this.cachedData = null; 1733 // keep token as it's used by the call to get the log 1734 // this.token = null; 1735 if (this.jobStatusTimer != null) { 1736 this.jobStatusTimer.stop(); 1737 this.jobStatusTimer = null; 1738 } 1739 this.progressDialog.buttons[2].disable(); // cancel button 1740 1741 if( Ext.getCmp('runAnalysisProgressBar')!=null){ 1742 Ext.getCmp('runAnalysisProgressBar').reset(); 1743 Ext.getCmp('runAnalysisProgressBar').updateText('Analysis aborted.'); 1744 } 1745 } 1746 1747 }); 1748 1749 /** 1750 * A static instance of the {@link Monk.component.DataManager} class. 1751 */ 1752 Monk.component.dataManager = new Monk.component.DataManager(); 1753