using System;
using System.IO;
using System.Collections;
using System.Drawing;
using System.ComponentModel;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
namespace FastReport.Utils
{
///
/// Specifies the target for the serialize operation.
///
public enum SerializeTo
{
///
/// Serialize to the report file.
///
Report,
///
/// Serialize to the preview pages.
///
Preview,
///
/// Serialize to the source pages of a preview.
///
SourcePages,
///
/// Serialize to the designer's clipboard.
///
Clipboard,
///
/// Serialize to the designer's undo/redo buffer.
///
Undo
}
internal class DiffEventArgs
{
private object obj;
private object diffObject;
public object Object
{
get { return obj; }
set { obj = value; }
}
public object DiffObject
{
get { return diffObject; }
set { diffObject = value; }
}
}
internal delegate void DiffEventHandler(object sender, DiffEventArgs e);
///
/// The writer used to serialize object's properties to a report file.
///
public class FRWriter : IDisposable
{
#region Fields
private XmlDocument doc;
private XmlItem root;
private XmlItem curItem;
private XmlItem curRoot;
//private StringBuilder FText;
private object diffObject;
private bool saveChildren;
private bool writeHeader;
private BlobStore blobStore;
private SerializeTo serializeTo;
private Hashtable diffObjects;
#endregion
#region Properties
internal event DiffEventHandler GetDiff;
internal BlobStore BlobStore
{
get { return blobStore; }
set { blobStore = value; }
}
///
/// Gets or sets current xml item name.
///
public string ItemName
{
get { return curItem.Name; }
set { curItem.Name = value; }
}
///
/// Gets or sets target of serialization.
///
public SerializeTo SerializeTo
{
get { return serializeTo; }
set { serializeTo = value; }
}
///
/// Gets the ethalon object to compare with.
///
public object DiffObject
{
get { return diffObject; }
}
///
/// Gets or sets a value that determines whether is necessary to serialize child objects.
///
public bool SaveChildren
{
get { return saveChildren; }
set { saveChildren = value; }
}
///
/// Gets or sets a value that determines whether is necessary to add xml header.
///
public bool WriteHeader
{
get { return writeHeader; }
set { writeHeader = value; }
}
#endregion
#region Private Methods
private string PropName(string name)
{
return serializeTo == SerializeTo.Preview ? ShortProperties.GetShortName(name) : name;
}
#endregion
#region Public Methods
///
/// Serializes the specified object.
///
/// The object to serialize.
///
/// The object must implement the interface. This method
/// invokes the Serialize method of the object.
///
/// This example demonstrates the use of writer.
///
/// public void Serialize(FRWriter writer)
/// {
/// // get the etalon object. It will be used to write changed properties only.
/// Base c = writer.DiffObject as Base;
///
/// // write the type name
/// writer.ItemName = ClassName;
///
/// // write properties
/// if (Name != "")
/// writer.WriteStr("Name", Name);
/// if (Restrictions != c.Restrictions)
/// writer.WriteValue("Restrictions", Restrictions);
///
/// // write child objects if allowed
/// if (writer.SaveChildren)
/// {
/// foreach (Base child in ChildObjects)
/// {
/// writer.Write(child);
/// }
/// }
/// }
///
///
public void Write(IFRSerializable obj)
{
Write(obj, null);
}
///
/// Serializes the object using specified etalon.
///
/// The object to serialize.
/// The etalon object.
public void Write(IFRSerializable obj, object diff)
{
if (obj == null)
return;
XmlItem saveCurItem = curItem;
XmlItem saveCurRoot = curRoot;
//StringBuilder saveText = FText;
object saveDiffObject = diffObject;
try
{
//FText = new StringBuilder();
curItem = curItem == null ? root : curItem.Add();
curRoot = curItem;
diffObject = diff;
if (obj is Base && SerializeTo == SerializeTo.Preview)
{
diffObject = (obj as Base).OriginalComponent;
curItem.Name = diffObject != null ? (obj as Base).Alias : (obj as Base).ClassName;
}
if (GetDiff != null)
{
DiffEventArgs e = new DiffEventArgs();
e.Object = obj;
GetDiff(this, e);
diffObject = e.DiffObject;
}
if (diffObject == null)
{
try
{
Type objType = obj.GetType();
if (!diffObjects.Contains(objType))
diffObjects[objType] = Activator.CreateInstance(objType);
diffObject = diffObjects[objType];
}
catch
{
}
}
obj.Serialize(this);
}
finally
{
//if (FText.Length > 0)
// FText.Remove(FText.Length - 1, 1);
//FCurRoot.Text = FText.ToString();
//FText = saveText;
curItem = saveCurItem;
curRoot = saveCurRoot;
diffObject = saveDiffObject;
}
}
///
/// Writes a string property.
///
/// Property name.
/// Property value.
public void WriteStr(string name, string value)
{
curRoot.SetProp(PropName(name), value);
//FText.Append(PropName(name));
//FText.Append("=\"");
//FText.Append(Converter.ToXml(value));
//FText.Append("\" ");
}
///
/// Writes a boolean property.
///
/// Property name.
/// Property value.
public void WriteBool(string name, bool value)
{
curRoot.SetProp(PropName(name), value ? "true" : "false");
// FText.Append(PropName(name));
//FText.Append("=\"");
//FText.Append(value ? "true" : "false");
//FText.Append("\" ");
}
///
/// Writes an integer property.
///
/// Property name.
/// Property value.
public void WriteInt(string name, int value)
{
curRoot.SetProp(PropName(name), value.ToString());
//FText.Append(PropName(name));
//FText.Append("=\"");
//FText.Append(value.ToString());
//FText.Append("\" ");
}
///
/// Writes a float property.
///
/// Property name.
/// Property value.
public void WriteFloat(string name, float value)
{
curRoot.SetProp(PropName(name), value.ToString(CultureInfo.InvariantCulture.NumberFormat));
//FText.Append(PropName(name));
//FText.Append("=\"");
//FText.Append(value.ToString(CultureInfo.InvariantCulture.NumberFormat));
//FText.Append("\" ");
}
///
/// Writes a double property.
///
/// Property name.
/// Property value.
public void WriteDouble(string name, double value)
{
curRoot.SetProp(PropName(name), value.ToString(CultureInfo.InvariantCulture.NumberFormat));
//FText.Append(PropName(name));
//FText.Append("=\"");
//FText.Append(value.ToString(CultureInfo.InvariantCulture.NumberFormat));
//FText.Append("\" ");
}
///
/// Writes an enumeration property.
///
/// Property name.
/// Property value.
public void WriteValue(string name, object value)
{
curRoot.SetProp(PropName(name), value != null ? Converter.ToString(value) : "null");
//FText.Append(PropName(name));
//FText.Append("=\"");
//FText.Append(value != null ? Converter.ToXml(value) : "null");
//FText.Append("\" ");
}
///
/// Writes an object reference property.
///
/// Property name.
/// Property value.
public void WriteRef(string name, Base value)
{
curRoot.SetProp(PropName(name), value != null ? value.Name : "null");
//FText.Append(PropName(name));
//FText.Append("=\"");
//FText.Append(value != null ? value.Name : "null");
//FText.Append("\" ");
}
///
/// Writes a standalone property value.
///
/// Name of property.
/// Property value.
///
/// This method produces the following output:
/// <PropertyName>PropertyValue</PropertyName>
///
public void WritePropertyValue(string name, string value)
{
XmlItem item = curItem.Add();
item.Name = name;
item.Value = value;
}
///
/// Determines if two objects are equal.
///
/// The first object.
/// The second object.
/// true if objects will be serialized to the same value.
public bool AreEqual(object obj1, object obj2)
{
if (obj1 == obj2)
return true;
if (obj1 == null || obj2 == null)
return false;
string s1 = Converter.ToString(obj1);
string s2 = Converter.ToString(obj2);
return s1 == s2;
}
///
/// Disposes the writer.
///
public void Dispose()
{
doc.Dispose();
foreach (object obj in diffObjects.Values)
{
if (obj is IDisposable)
(obj as IDisposable).Dispose();
}
}
///
/// Saves the writer output to a stream.
///
/// Stream to save to.
public void Save(Stream stream)
{
doc.AutoIndent = serializeTo == SerializeTo.Report;
doc.WriteHeader = WriteHeader;
doc.Save(stream);
}
#endregion
///
/// Initializes a new instance of the FRWriter class with default settings.
///
public FRWriter()
{
doc = new XmlDocument();
root = doc.Root;
//FText = new StringBuilder();
saveChildren = true;
writeHeader = true;
diffObjects = new Hashtable();
}
///
/// Initializes a new instance of the FRWriter class with specified xml item that will
/// receive writer's output.
///
/// The xml item that will receive writer's output.
public FRWriter(XmlItem root) : this()
{
this.root = root;
}
}
}