blob: 253cf10106f712458d5677617a18c010c5c4ac5d [file] [log] [blame]
/// <summary>
/// Class used to parse csdl to create the metatdata object
/// </summary>
///
namespace DataJS.Tests
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
public static class CsdlReader
{
static readonly string knownNamespace = "http://docs.oasis-open.org";
static readonly string[] repeatingElements =
{
"Action",
"ActionImport",
"Annotation",
"Annotations",
"Apply",
"Binary",
"Bool",
"Cast",
"Collection",
"ComplexType",
"Date",
"DateTimeOffset",
"Decimal",
"Duration",
"EntitySet",
"EntityType",
"EnumMember",
"EnumType",
"Float",
"Function",
"FunctionImport",
"Guid",
"If",
"Int",
"IsOf",
"Key",
"LabeledElement",
"LabeledElementReference",
"Member",
"NavigationProperty",
"NavigationPropertyBinding",
"NavigationPropertyPath",
"Null",
"OnDelete",
"Path",
"Parameter",
"Property",
"PropertyPath",
"PropertyRef",
"PropertyValue",
"Record",
"ReferentialConstraint",
"String",
"Schema",
"Singleton",
"Term",
"TimeOfDay",
"TypeDefinition",
"UrlRef",
"Reference",
"Include",
"IncludeAnnotations"
};
public static Dictionary<string, object> ReadCsdl(TextReader payload)
{
return BuildElementJsonObject(XElement.Load(payload));
}
/// <summary>
/// Build the attribute object
/// </summary>
/// <param name="xmlAttributes">IEnumberable of XAttributes to build the attribute object</param>
/// <returns>The JsonObject containing the name-value pairs for an element's attributes</returns>
static Dictionary<string, object> BuildAttributeJsonObject(IEnumerable<XAttribute> xmlAttributes)
{
Dictionary<string, object> jsonObject = new Dictionary<string, object>();
foreach (XAttribute attribute in xmlAttributes)
{
if (!attribute.IsNamespaceDeclaration)
{
string attributeNamespace = attribute.Name.Namespace.ToString();
if (string.IsNullOrEmpty(attributeNamespace) ||
attributeNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase))
{
jsonObject[MakeFirstLetterLowercase(attribute.Name.LocalName)] = attribute.Value;
}
}
}
return jsonObject;
}
/// <summary>
/// Creates a JsonObject from an XML container element with each attribute or subelement as a property
/// </summary>
/// <param name="container">The XML container</param>
/// <param name="buildValue">Function that builds a value from a property element</param>
/// <returns>The JsonObject containing the name-value pairs</returns>
public static Dictionary<string, object> BuildElementJsonObject(XElement container)
{
if (container == null)
{
return null;
}
Dictionary<string, object> jsonObject = new Dictionary<string, object>();
string keyName = MakeFirstLetterLowercase(container.Name.LocalName);
if (container.HasAttributes || container.HasElements)
{
Dictionary<string, List<Dictionary<string, object>>> repeatingObjectArrays = new Dictionary<string, List<Dictionary<string, object>>>();
jsonObject = BuildAttributeJsonObject(container.Attributes());
foreach (XElement propertyElement in container.Elements())
{
string propertyName = MakeFirstLetterLowercase(propertyElement.Name.LocalName);
string properyNamespace = propertyElement.Name.Namespace.ToString();
if (string.IsNullOrEmpty(properyNamespace) || properyNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase))
{
// Check to see if the element is repeating and needs to be an array
if (repeatingElements.Contains(propertyElement.Name.LocalName))
{
// See if property was already created as an array, if not then create it
if (!repeatingObjectArrays.ContainsKey(propertyName))
{
repeatingObjectArrays.Add(propertyName, new List<Dictionary<string, object>>());
}
repeatingObjectArrays[propertyName].Add(BuildElementJsonObject(propertyElement));
}
else
{
jsonObject[propertyName] = BuildElementJsonObject(propertyElement);
}
}
}
foreach (string key in repeatingObjectArrays.Keys)
{
jsonObject[key] = repeatingObjectArrays[key].ToArray();
}
}
else
{
jsonObject[MakeFirstLetterLowercase(container.Name.LocalName)] = container.Value;
}
return jsonObject;
}
/// <summary>
/// Makes the first letter of a string lowercase
/// </summary>
/// <param name="name">The string to be modified</param>
/// <returns>Modified string</returns>
private static string MakeFirstLetterLowercase(string str)
{
if (!string.IsNullOrWhiteSpace(str))
{
if (str.Length > 1 && !(str[1].ToString() == str[1].ToString().ToUpper()))
{
return str[0].ToString().ToLower() + str.Substring(1);
}
else
{
return str;
}
}
return str;
}
}
}