using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
namespace Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStability.Assemblers
{
///
/// Extnesion helper methods
///
public static class DtoHelperServices
{
///
/// TODO: Solve this hack in a good way!!!
///
///
///
public static string ToUtf8EncodedStringFix(this XDocument doc)
{
string xmlData = doc.ToString();
// Hack to
if (!xmlData.Contains("encoding"))
xmlData = "" + Environment.NewLine + xmlData;
return xmlData;
}
///
/// Assembles a XElement from a domain object
///
///
/// Only public properties will be used
///
///
///
///
///
public static XElement ToXElement(this TDomaiObject domainObject, string elementName)
{
return ToXElement(domainObject, elementName, null);
}
///
/// Assembles a XElement from a domain object
///
///
/// Only public properties will be used
///
///
///
///
///
///
public static XElement ToXElement(this TDomaiObject domainObject, string elementName, string elementNamespace)
{
if (elementNamespace.HasValidStringValue())
{
XNamespace ns = elementNamespace;
return ToXElement(domainObject, elementName, ns);
}
return ToXElement(domainObject, elementName, null);
}
///
/// Assembles a XElement from a domain object
///
///
/// Only public properties will be used
///
///
///
///
///
///
public static XElement ToXElement(this TDomaiObject domainObject, string elementName, XNamespace elementNamespace)
{
if (domainObject.Equals(default(TDomaiObject)))
return null;
if (!elementName.HasValidStringValue())
throw new DtoAssemblerException("There is no element name specified");
if (elementNamespace != null)
{
return new XElement(elementNamespace + elementName).Materialize(domainObject);
}
return new XElement(elementName).Materialize(domainObject);
}
///
///
///
///
///
///
///
///
public static XElement ToDto(this TDomainObject domainObj, IDtoAssembler assembler, XNamespace elementNamespace)
where TDomainObject : new()
{
XElement element = assembler.CreateDataTransferObject(domainObj);
if (element == null)
return null;
// replace the element name with the given namespace
var tmp = new XElement(elementNamespace + assembler.ElementName);
element.Name = tmp.Name;
return element;
}
///
///
///
///
///
///
///
public static XElement ToDto(this IEnumerable collection, XName elementName, XName itemElementName)
{
return ToDto(collection, elementName, itemElementName, null);
}
///
///
///
///
///
///
///
///
///
public static XElement ToDto(this IEnumerable collection, XName elementName, XName itemElementName, XName itemAttributeName)
{
if (elementName == null)
throw new ArgumentNullException("elementName");
if (itemElementName == null)
throw new ArgumentNullException("itemElementName");
var el = new XElement(elementName);
if (itemAttributeName == null)
{
foreach (TDomainObject item in collection)
el.Add(new XElement(itemElementName, item));
}
else
{
foreach (TDomainObject item in collection)
el.Add(new XElement(itemElementName, new XAttribute(itemAttributeName, item)));
}
return el;
}
///
///
///
///
///
///
///
///
public static XElement ToDto(this IEnumerable domainObjCollection, IDtoCollectionAssembler assembler, XNamespace elementNamespace)
where TDomainObject : new()
{
XElement element = assembler.CreateDataTransferObject(domainObjCollection);
if (element == null)
return null;
// replace the element name with the given namespace
var tmp = new XElement(elementNamespace + assembler.ElementName);
element.Name = tmp.Name;
return element;
}
///
///
///
///
///
///
///
public static IEnumerable ToDtoIterator(this IEnumerable domainObjColl, IDtoAssembler assembler)
{
foreach (T item in domainObjColl)
yield return assembler.CreateDataTransferObject(item);
}
///
///
///
///
///
///
///
public static IEnumerable ToDomainObjectIterator(this IEnumerable dtoObjColl, IDtoAssembler assembler)
{
foreach (XElement item in dtoObjColl)
yield return assembler.CreateDomainObject(item);
}
///
///
///
///
///
///
///
public static IEnumerable ToDomainObjectIterator(XElement element, string elementName, string itemElementName, string itemAttributeName)
{
IEnumerable dto = from x in element.Descendants()
where x.Name.LocalName == itemElementName && x.Parent.Name.LocalName == elementName
select x;
foreach (XElement item in dto)
yield return item.AttributeAs(itemAttributeName);
}
public static XElement GetFirstOrDefaultElementByLocalName(this XDocument doc, string localName)
{
return (from x in doc.Descendants()
where x.Name.LocalName == localName
select x).FirstOrDefault();
}
///
///
///
///
///
///
///
public static IEnumerable ToPropertyMap(this T type, Stream xsdStream)
{
return null;
}
///
///
///
///
///
///
///
public static IEnumerable ToPropertyMap(this T type, XDocument xsdDocument)
{
return null;
}
///
///
///
///
///
///
public static IEnumerable ToPropertyMap(this T type)
{
foreach (PropertyInfo pInfo in type.GetType().GetProperties())
{
object val = null;
try
{
val = pInfo.GetValue(type, null);
}
catch
{
throw new DtoPropertyMapException(string.Format("Error reading property {0} of type {1}", pInfo.Name, pInfo.ReflectedType.Name));
}
if (val != null)
{
yield return new DtoPropertyAttriubteMapping()
{
PropertyName = pInfo.Name,
AttributeName = pInfo.Name,
Importance = DtoPropertyImportance.Optional
};
}
}
}
private static IEnumerable GetAttributes(XDocument doc, string elementName)
{
IEnumerable element = from x in doc.Descendants()
where x.Attribute("name") != null && x.Attribute("name").Value == elementName
select x;
if (element.Any())
{
if (element.First().Name.LocalName == "complexType")
{
IEnumerable q1 = from x in element.Elements()
where x.Name.LocalName == "attribute"
select new AttributeInfo()
{
Name = x.Attribute("name").Value,
Use = x.Attribute("use") == null ? "optional" : x.Attribute("use").Value
};
return q1;
}
if (element.First().Name.LocalName == "element" &&
element.ElementAt(0).HasElements &&
element.ElementAt(0).Elements().ElementAt(0).Name.LocalName == "complexType")
{
IEnumerable q2 = from x in element.ElementAt(0).Elements().ElementAt(0).Elements()
where x.Name.LocalName == "attribute"
select new AttributeInfo()
{
Name = x.Attribute("name").Value,
Use = x.Attribute("use") == null ? "optional" : x.Attribute("use").Value
};
return q2;
}
}
return new List() {};
}
///
///
///
///
///
///
public static IEnumerable ToPropertyMap(this T type, string elementName, XDocument doc)
{
IEnumerable refTable = GetAttributes(doc, elementName);
foreach (PropertyInfo pInfo in type.GetType().GetProperties())
{
if (refTable.Count() > 0)
{
// does the property exist in the xsd?
IEnumerable q = from x in refTable
where x.Name.Equals(pInfo.Name, StringComparison.InvariantCultureIgnoreCase)
select x;
if (q.Any())
{
// ok we have a property attribute match we can now
// safely create and return the mapping object
AttributeInfo item = q.Single();
yield return new DtoPropertyAttriubteMapping()
{
PropertyName = pInfo.Name,
AttributeName = item.Name,
Importance = item.Use == "optional" ?
DtoPropertyImportance.Optional : DtoPropertyImportance.Required
};
}
}
}
}
///
/// Materializes a simple object with the data from a xml file
///
///
/// Materialization happens on equal name basis. So the attribute
/// local name should be the same as the property name. Also the property type should
/// be known by the this method
///
///
///
///
public static T Materialize(this T dest, XElement src)
{
return Materialize(dest, src, null);
}
///
/// Materializes a domain object with the data from a xml file based on a property map
///
///
///
///
///
public static T Materialize(this T dest, XElement src, DtoPropertyAttributeMap propertyMap)
{
bool hasPropertyMap = propertyMap != null && propertyMap.Count > 0;
if (src.HasAttributes)
{
XAttribute att = src.FirstAttribute;
try
{
do
{
string attName = att.Name.LocalName;
object v = att.Value;
if (v != null)
{
PropertyInfo pInfo = null;
DtoPropertyAttriubteMapping mapItem = null;
if (hasPropertyMap)
{
mapItem = propertyMap.GetByAttributeName(attName);
// Is the property found in the map?
if (mapItem != null)
pInfo = typeof (T).GetProperty(mapItem.PropertyName);
// else throw ?
}
else
// No property map so try to get property name based on
// the attribute name
pInfo = typeof (T).GetProperty(attName);
if (pInfo != null)
{
// does the mapping contains a translation rule for
// the object to parse?
if (mapItem != null && mapItem.ToPropertyTranslationRule != null)
{
pInfo.SetObjectValue(dest, v, mapItem.ToPropertyTranslationRule);
}
else
{
pInfo.SetObjectValue(dest, v, null);
}
}
}
} while ((att = att.NextAttribute) != null);
}
catch (DtoAssemblerConversionException ex)
{
throw new DtoAssemblerConversionException(ex.Message);
}
catch
{
throw;
}
}
return dest;
}
///
/// Extension helper method which materializes a xml element with attributes and its values
///
///
///
///
///
public static XElement Materialize(this XElement element, T src)
{
var map = new DtoPropertyAttributeMap();
foreach (PropertyInfo pInfo in src.GetType().GetProperties())
{
object val = pInfo.GetValue(src, null);
if (val != null)
{
map.Add(pInfo.Name, new DtoPropertyAttriubteMapping()
{
PropertyName = pInfo.Name,
AttributeName = pInfo.Name,
Importance = DtoPropertyImportance.Optional
});
}
}
return element.Materialize(src, map);
}
///
/// Extension helper method which materializes an xml element with attributes and its values
///
/// Throws a required field exception if property is set to required in property map
///
///
///
///
///
public static XElement Materialize(this XElement element, T src, DtoPropertyAttributeMap propertyMap)
{
PropertyInfo pInfo;
foreach (var item in propertyMap)
{
pInfo = typeof (T).GetProperty(item.Key);
object val = pInfo.GetValue(src, null);
if (val != null)
{
string attName = item.Value.AttributeName;
element.Add(new XAttribute(attName, val));
}
else
{
// Throw required field exception..
if (item.Value.Importance == DtoPropertyImportance.Required)
throw new MissingRequiredValueException(item.Key);
}
}
return element;
}
///
///
///
///
///
///
///
public static XElement SetNamespace(this XElement element, string elementName, string elementNamespace)
{
XNamespace ns = elementNamespace;
element.Name = new XElement(ns + elementName).Name;
return element;
}
public static XElement SetNamespace(this XElement element, XNamespace elementNamespace)
{
element.Name = elementNamespace.GetName(element.Name.LocalName);
return element;
}
///
///
///
///
///
public static bool HasValidStringValue(this string value)
{
return !string.IsNullOrEmpty(value) && value.Trim() != "";
}
public static T ToEnum(this object value, IDictionary lookup)
{
if (value == null)
throw new ArgumentNullException("value");
return value.ToEnumType(lookup);
}
public static T AttributeAs(this XElement element, XName name)
{
var xAttribute = element.Attribute(name);
if (xAttribute != null)
return xAttribute.Value.ToType();
return default(T);
}
#region Nested type: AttributeInfo
private struct AttributeInfo
{
public string Name;
public string Use;
//public string Type;
}
#endregion
}
}