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 } }