/// <summary> /// Checks to see if symbols have already been downloaded. If they haven't, they are loaded from the server /// in the background. /// </summary> /// <param name="forceReload">If true the symbols will be loaded even if there are already symbols present.</param> public void LoadSymbolsAsync(bool forceReload) { if (_symbolsDownloading) { return; } _symbolsDownloading = true; _symbolsDownloadCancel = false; ThreadPool.QueueUserWorkItem( (state) => { try { // download apex, parse it and then save to cache if (forceReload || FileUtility.IsFolderEmpty(SymbolsFolder)) { App.Instance.Dispatcher.Invoke(() => App.SetStatus("Downloading symbols and updating search index...")); object[] parameters = state as object[]; Project project = parameters[0] as Project; SalesForceClient client = parameters[1] as SalesForceClient; LanguageManager language = parameters[2] as LanguageManager; SearchIndex searchIndex = new SearchIndex(project.SearchFolder, true); try { project._symbolsDownloaded.Reset(); // get class ids DataSelectResult data = client.Data.Select("SELECT Id FROM ApexClass"); Queue <string> classIds = new Queue <string>(); foreach (DataRow row in data.Data.Rows) { classIds.Enqueue(row["Id"] as string); } // download classes in groups of 25 while (classIds.Count > 0) { if (project._symbolsDownloadCancel) { break; } StringBuilder query = new StringBuilder("SELECT Id, Name, Body FROM ApexClass WHERE Id IN ("); for (int i = 0; i < 25 && classIds.Count > 0; i++) { query.AppendFormat("'{0}',", classIds.Dequeue()); } query.Length = query.Length - 1; query.Append(")"); DataSelectResult classData = client.Data.Select(query.ToString()); foreach (DataRow row in classData.Data.Rows) { string body = row["Body"] as string; bool isGenerated = false; if (body == "(hidden)") { body = Client.Meta.GetGeneratedContent(row["Id"] as string); isGenerated = true; } // parse symbols language.ParseApex(body, false, true, isGenerated); // add to search index searchIndex.Add( row["Id"] as string, String.Format("classes/{0}.cls", row["Name"]), "ApexClass", row["Name"] as string, body); } } // download symbols for SObjects if (!project._symbolsDownloadCancel) { SObjectTypePartial[] sObjects = client.Data.DescribeGlobal(); foreach (SObjectTypePartial sObject in sObjects) { if (project._symbolsDownloadCancel) { break; } SObjectType sObjectDetail = client.Data.DescribeObjectType(sObject); language.UpdateSymbols( ConvertToSymbolTable(sObjectDetail), false, true, false); } } // remove symbols and search index if the download was interupted if (_symbolsDownloadCancel) { if (searchIndex != null) { searchIndex.Clear(); } FileUtility.DeleteFolderContents(project.SymbolsFolder); } } finally { if (searchIndex != null) { searchIndex.Dispose(); } project._symbolsDownloaded.Set(); } } // load cached symbols else { App.Instance.Dispatcher.Invoke(() => App.SetStatus("Loading symbols...")); XmlSerializer ser = new XmlSerializer(typeof(SymbolTable)); foreach (string file in Directory.GetFiles(SymbolsFolder)) { using (FileStream fs = File.OpenRead(file)) { SymbolTable st = ser.Deserialize(fs) as SymbolTable; Language.UpdateSymbols(st, false, false, false); fs.Close(); } } } } catch (Exception err) { App.Instance.Dispatcher.Invoke(() => App.HandleException(err)); } finally { App.Instance.Dispatcher.Invoke(() => App.SetStatus(null)); _symbolsDownloading = false; } }, new object[] { this, Client, Language }); }
/// <summary> /// Export the resulting data. /// </summary> public void ExportResult() { if (!IsExportDataResultEnabled) { return; } if (DataResult != null) { // ask user if they want to export all data if there is more than one page bool allData = false; if (DataResult.IsMore) { string answer = App.MessageUser( "Would you like to export all remaining data from your query or only the data that is currently displayed?", "Export Data", System.Windows.MessageBoxImage.Question, new string[] { "All data", "Currently displayed data", "Cancel" }); if (answer == "Cancel") { return; } allData = (answer == "All data"); } // get file name for export Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog(); dlg.Filter = "CSV Files (*.csv)|*.csv"; dlg.Title = "Export data"; dlg.DefaultExt = "csv"; dlg.OverwritePrompt = true; bool?dlgResult = dlg.ShowDialog(); if (dlgResult.HasValue && dlgResult.Value) { using (StreamWriter writer = new StreamWriter(File.Open(dlg.FileName, FileMode.OpenOrCreate))) { // write column names for (int i = 0; i < DataResult.Data.Columns.Count; i++) { writer.Write(NormCSVText(DataResult.Data.Columns[i].ColumnName)); if (i != DataResult.Data.Columns.Count - 1) { writer.Write(","); } } writer.WriteLine(); DataSelectResult result = DataResult; while (result != null) { // write rows foreach (DataRow row in result.Data.Rows) { for (int i = 0; i < DataResult.Data.Columns.Count; i++) { writer.Write(NormCSVText(row[i] as string)); if (i != DataResult.Data.Columns.Count - 1) { writer.Write(","); } } writer.WriteLine(); } // check for more data if (result.IsMore && allData) { result = Project.Client.Data.Select(result); } else { result = null; } } // close stream writer.Flush(); writer.Close(); } } } }