SonicAudioTools/Source/SonicAudioLib/CriMw/CriTable.cs
2017-06-21 01:19:47 +03:00

239 lines
6.6 KiB
C#

using System;
using System.IO;
using System.Linq;
using SonicAudioLib.IO;
using SonicAudioLib.FileBases;
using System.Xml;
using System.Xml.Linq;
namespace SonicAudioLib.CriMw
{
public class CriTable : FileXmlBase
{
private CriFieldCollection fields;
private CriRowCollection rows;
private string tableName = "(no name)";
private CriTableWriterSettings writerSettings;
public CriFieldCollection Fields
{
get
{
return fields;
}
}
public CriRowCollection Rows
{
get
{
return rows;
}
}
public string TableName
{
get
{
return tableName;
}
set
{
tableName = value;
}
}
public CriTableWriterSettings WriterSettings
{
get
{
return writerSettings;
}
set
{
writerSettings = value;
}
}
public void Clear()
{
rows.Clear();
fields.Clear();
}
public CriRow NewRow()
{
CriRow criRow = new CriRow(this);
foreach (CriField criField in fields)
{
criRow.Records.Add(new CriRowRecord { Field = criField, Value = criField.DefaultValue });
}
return criRow;
}
public override void Read(Stream source)
{
using (CriTableReader reader = CriTableReader.Create(source))
{
tableName = reader.TableName;
for (int i = 0; i < reader.NumberOfFields; i++)
{
fields.Add(reader.GetFieldName(i), reader.GetFieldType(i), reader.GetFieldValue(i));
}
while (reader.Read())
{
rows.Add(reader.GetValueArray());
}
}
}
public override void Write(Stream destination)
{
using (CriTableWriter writer = CriTableWriter.Create(destination, writerSettings))
{
writer.WriteStartTable(tableName);
writer.WriteStartFieldCollection();
foreach (CriField criField in fields)
{
bool useDefaultValue = false;
object defaultValue = null;
if (rows.Count > 1)
{
useDefaultValue = true;
defaultValue = rows[0][criField];
if (rows.Any(row => !row[criField].Equals(defaultValue)))
{
useDefaultValue = false;
}
}
else if (rows.Count == 0)
{
useDefaultValue = true;
}
if (useDefaultValue)
{
writer.WriteField(criField.FieldName, criField.FieldType, defaultValue);
}
else
{
writer.WriteField(criField.FieldName, criField.FieldType);
}
}
writer.WriteEndFieldCollection();
foreach (CriRow criRow in rows)
{
writer.WriteRow(true, criRow.GetValueArray());
}
writer.WriteEndTable();
}
}
public override void ReadXml(XmlReader reader)
{
var document = XDocument.Load(reader);
foreach (XElement element in document.Root.Element(nameof(Fields)).Elements(nameof(CriField)))
{
fields.Add(
element.Element(nameof(CriField.FieldName)).Value,
Type.GetType(element.Element(nameof(CriField.FieldType)).Value)
);
}
foreach (XElement element in document.Root.Element(nameof(Rows)).Elements(nameof(CriRow)))
{
CriRow row = NewRow();
foreach (CriRowRecord record in row.Records)
{
if (record.Field.FieldType == typeof(byte[]))
{
record.Value = Convert.FromBase64String(element.Element(record.Field.FieldName).Value);
}
else
{
record.Value = Convert.ChangeType(element.Element(record.Field.FieldName).Value, record.Field.FieldType);
}
}
rows.Add(row);
}
}
public override void WriteXml(XmlWriter writer)
{
var document = new XDocument(new XElement(nameof(CriTable)));
document.Root.Add(new XElement(nameof(TableName), TableName));
var fieldsElement = new XElement(nameof(Fields));
foreach (CriField field in fields)
{
var fieldElement = new XElement(nameof(CriField));
fieldElement.Add(
new XElement(nameof(field.FieldName), field.FieldName),
new XElement(nameof(field.FieldType), field.FieldType.Name)
);
fieldsElement.Add(fieldElement);
}
document.Root.Add(fieldsElement);
var rowsElement = new XElement(nameof(Rows));
foreach (CriRow row in rows)
{
var rowElement = new XElement(nameof(CriRow));
foreach (CriRowRecord record in row.Records)
{
if (record.Value is byte[] bytes)
{
rowElement.Add(new XElement(record.Field.FieldName, Convert.ToBase64String(bytes)));
}
else
{
rowElement.Add(new XElement(record.Field.FieldName, record.Value));
}
}
rowsElement.Add(rowElement);
}
document.Root.Add(rowsElement);
document.Save(writer);
}
public CriTable()
{
fields = new CriFieldCollection(this);
rows = new CriRowCollection(this);
writerSettings = new CriTableWriterSettings();
}
public CriTable(string tableName) : this()
{
this.tableName = tableName;
}
}
}