Newer
Older
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

Markus Quaritsch
committed
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Xml;
using System.Xml.Schema;
using HashingTool.Helper;
using HashingTool.Util;
namespace HashingTool.ViewModel.UserControl
{
public enum XmlFileStatus
{
Unknown, // no file selected, outline
Invalid, // reading failed, no xml, etc. red
InvalidXML, // does not validate against known schemas
IncorrectContent, // content validation failed
ValidXML // green
}

Markus Quaritsch
committed
public interface IErrorLogger
{
void LogError(string message);
}
public class XMLFileSelector : ObservableObject, IErrorLogger
{
private string _source;
private XmlFileStatus _isValid;
private bool _busy;
private readonly bool _validate;
private XmlDocument _document;

Markus Quaritsch
committed
private readonly Func<XmlDocument, IErrorLogger, bool?> _contentVerification;

Markus Quaritsch
committed
private bool? _contentValid;
private RelayCommand _browseFileCommand;

Markus Quaritsch
committed
private string _prefix;

Markus Quaritsch
committed
public XMLFileSelector(IOService ioservice, string prefix, bool validate = false,
Func<XmlDocument, IErrorLogger, bool?> contentCheck = null)

Markus Quaritsch
committed
IoService = ioservice;

Markus Quaritsch
committed
_prefix = prefix;
_browseFileCommand = new RelayCommand(BrowseXMLFile, () => !_busy);
XMLValidationErrors = new ObservableCollection<string>();

Markus Quaritsch
committed
HasContentValidation = contentCheck != null;

Markus Quaritsch
committed
_contentVerification = contentCheck ?? ((x, c) => null);
Source = "";
RaisePropertyChanged("ValidateInput");

Markus Quaritsch
committed
RaisePropertyChanged("HasContentValidation");
}
public XmlDocument Document
{
get { return _document; }
private set {
if (_document == value) {
return;
}
_document = value;
RaisePropertyChanged("Document");
}
}
public string Source
{
get { return _source; }
private set {
if (_source == value) {
return;
}

Markus Quaritsch
committed
SetXMLFile(value);
_source = value;
RaisePropertyChanged("Source");
}
}
public bool ValidateInput
{
get { return _validate; }
}
public XmlFileStatus IsValid
{
get { return _isValid; }
private set {
if (_isValid == value) {
return;
}
_isValid = value;
RaisePropertyChanged("IsValid");
SetToolTip(value);
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
private void SetToolTip(XmlFileStatus value)
{
var toolTip = "";
switch (value) {
case XmlFileStatus.Unknown:
toolTip = "Select XML File file";
break;
case XmlFileStatus.Invalid:
toolTip = "Invalid file";
break;
case XmlFileStatus.InvalidXML:
toolTip = "XML Schema validation failed";
break;
case XmlFileStatus.IncorrectContent:
toolTip = "Incorrect XML content";
break;
case XmlFileStatus.ValidXML:
toolTip = "OK";
break;
}
if (ToolTip == toolTip) {
return;
}
ToolTip = toolTip;
RaisePropertyChanged("ToolTip");
}
public string ToolTip { get; internal set; }
public ObservableCollection<string> XMLValidationErrors { get; set; }
public ICommand BrowseFileCommand
{
get { return _browseFileCommand; }

Markus Quaritsch
committed
public ICommand SetXMLFileCommnd
{
get { return new RelayCommand<string>(SetXMLFile, f => !_busy); }

Markus Quaritsch
committed
}

Markus Quaritsch
committed
private async void SetXMLFile(string fileName)
{
if (!File.Exists(fileName)) {
Document = null;
XMLValidationErrors.Clear();
ContentValid = null;
IsValid = XmlFileStatus.Unknown;

Markus Quaritsch
committed
return;
}
using (var stream = File.OpenRead(fileName)) {
await LoadXMLFile(stream);
}

Markus Quaritsch
committed
}
private async void BrowseXMLFile()
{
string filename;
using (var stream = IoService.OpenFileDialog(null, ".xml", "VECTO XML file|*.xml", out filename)) {
if (stream == null) {
return;
}
await LoadXMLFile(stream);
Source = filename;
}

Markus Quaritsch
committed
}
private async Task LoadXMLFile(Stream stream)
{
IsValid = XmlFileStatus.Unknown;

Markus Quaritsch
committed
ContentValid = null;
XMLValidationErrors.Clear();
var fileValid = XmlFileStatus.ValidXML;
bool? contentValid = null;
try {
var ms = new MemoryStream();
if (_validate) {
// copy stream beforehand if validation is needed later on
await stream.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);
stream.Seek(0, SeekOrigin.Begin);
}
var document = new XmlDocument();
var reader = XmlReader.Create(stream);
document.Load(reader);
Document = document;
var xmlValid = true;
if (_validate) {
xmlValid = await Validate(XmlReader.Create(ms));
if (!xmlValid) {
fileValid = XmlFileStatus.InvalidXML;
}
}
if (HasContentValidation) {

Markus Quaritsch
committed
contentValid = _contentVerification(document, this);
if (xmlValid && (contentValid == null || !contentValid.Value)) {
fileValid = XmlFileStatus.IncorrectContent;
}
}
} catch (Exception e) {

Markus Quaritsch
committed
LogError(e.Message);
fileValid = XmlFileStatus.Invalid;
} finally {
IsValid = fileValid;
ContentValid = contentValid;
_busy = false;
_browseFileCommand.RaiseCanExecuteChanged();

Markus Quaritsch
committed

Markus Quaritsch
committed
public void LogError(string message)
{
XMLValidationErrors.Add(String.Format("{0}: {1}", _prefix, message));
}

Markus Quaritsch
committed
public bool HasContentValidation { get; private set; }
public bool? ContentValid
{
get { return _contentValid; }
set {
if (_contentValid == value) {
return;
}
_contentValid = value;
RaisePropertyChanged("ContentValid");
}
}
private async Task<bool> Validate(XmlReader xml)

Markus Quaritsch
committed
var valid = true;

Markus Quaritsch
committed
var validator = new XMLValidator(r => { valid = r; },
Application.Current.Dispatcher.Invoke(
() =>

Markus Quaritsch
committed
LogError(string.Format("Validation {0} Line {2}: {1}",
s == XmlSeverityType.Warning ? "WARNING" : "ERROR",
e.ValidationEventArgs == null
? e.Exception.Message +
(e.Exception.InnerException != null ? Environment.NewLine + e.Exception.InnerException.Message : "")
: e.ValidationEventArgs.Message,
e.ValidationEventArgs == null ? 0 : e.ValidationEventArgs.Exception.LineNumber)));
});
await validator.ValidateXML(xml);
} catch (Exception e) {

Markus Quaritsch
committed
LogError(e.Message);
return valid;