/*
* Copyright (c) 2009 Craig Sutherland
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Xsl;
using ThoughtWorks.CruiseControl.Remote.Monitor;
using FastForward.WinCore.Configuration;
namespace FastForward.Monitor
{
///
/// Display the build history for a project.
///
public partial class BuildHistoryForm
: Form
{
#region Private fields
private Project project;
private ApplicationConfig configuration;
private ProjectBuild currentBuild;
private bool isLoaded;
private Dictionary templates = new Dictionary();
#endregion
#region Constructors
///
/// Initialise a new .
///
///
///
///
public BuildHistoryForm(Project project, ApplicationConfig configuration, Form owner)
{
InitializeComponent();
this.project = project;
this.configuration = configuration;
Text = "Build History: " + project.Name;
LoadTemplates();
RefreshData();
Owner = owner;
// Initialise the browser
using (var templateStream = this.GetType().Assembly.GetManifestResourceStream("FastForward.Monitor.BuildTemplate.htm"))
{
using (var reader = new StreamReader(templateStream))
{
var template = reader.ReadToEnd();
viewBrowser.DocumentText = template;
}
}
}
#endregion
#region Private methods
#region LoadTemplates()
///
/// Load the available templates.
///
private void LoadTemplates()
{
activeView.Items.Add(new BuildTemplateConfig
{
Name = "System",
FileName = "FastForward.Monitor.BuildSystemTemplate.xsl",
IsResource = true
});
activeView.Items.AddRange(configuration.BuildTemplates.ToArray());
activeView.SelectedIndex = 0;
activeView.SelectedIndexChanged += (o, e) => RefreshView();
}
#endregion
#region RefreshData()
///
/// Refresh the list of builds.
///
private void RefreshData()
{
buildsList.Items.Clear();
var orderedBuilds = (from record in project.Builds
orderby record.BuildDate descending
select record);
foreach (var build in orderedBuilds)
{
var status = build.IsSuccessful ? "Success" : "Failure";
var item = new ListViewItem(new string[] {
build.BuildDate.ToString(),
build.Label ?? string.Empty,
status
}, status);
item.Tag = build;
buildsList.Items.Add(item);
}
if (orderedBuilds.Count() > 0)
{
currentBuild = orderedBuilds.First();
}
RefreshView();
}
#endregion
#region RefreshView()
///
/// Refreshes the current view.
///
private void RefreshView()
{
if (isLoaded) viewBrowser.Document.Body.InnerHtml = GenerateView();
}
#endregion
#region GenerateView()
///
/// Generates the view to display.
///
///
private string GenerateView()
{
var currentTemplate = activeView.SelectedItem as BuildTemplateConfig;
if (!templates.ContainsKey(currentTemplate.Name))
{
// Load the XSL-T template
var newXslt = new XslCompiledTransform();
if (currentTemplate.IsResource)
{
using (var templateStream = this.GetType().Assembly.GetManifestResourceStream(currentTemplate.FileName))
{
using (var reader = XmlReader.Create(templateStream))
{
newXslt.Load(reader);
}
}
}
else
{
newXslt.Load(currentTemplate.FileName);
}
templates.Add(currentTemplate.Name, newXslt);
}
// Generate the output
var output = new StringBuilder();
try
{
using (var input = new StringReader(currentBuild.Log))
{
using (var reader = XmlReader.Create(input))
{
using (var writer = XmlWriter.Create(output))
{
templates[currentTemplate.Name].Transform(reader, writer);
}
}
}
}
catch (Exception error)
{
output.AppendFormat("Unable to read log: {0}", error.Message);
}
// Return the transformed view
return output.ToString();
}
#endregion
#endregion
#region Event handlers
#region refreshButton_Click()
///
/// The refresh button was clicked.
///
///
///
private void refreshButton_Click(object sender, EventArgs e)
{
RefreshData();
}
#endregion
#region buildsList_ItemSelectionChanged()
///
/// Handle an item being selected.
///
///
///
private void buildsList_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (buildsList.SelectedItems.Count == 1)
{
currentBuild = buildsList.SelectedItems[0].Tag as ProjectBuild;
RefreshView();
}
}
#endregion
#region viewBrowser_DocumentCompleted()
///
/// The template has loaded, now we can load the actual data.
///
///
///
private void viewBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
isLoaded = true;
viewBrowser.Document.Body.InnerHtml = GenerateView();
}
#endregion
#region saveButton_Click()
///
/// Allow the user to save the current report.
///
///
///
private void saveButton_Click(object sender, EventArgs e)
{
viewBrowser.ShowSaveAsDialog();
}
#endregion
#region printButton_Click()
///
/// Allow the user to print the current report.
///
///
///
private void printButton_Click(object sender, EventArgs e)
{
viewBrowser.ShowPrintDialog();
}
#endregion
#endregion
}
}