/// <summary> /// Validates the uom/value pair for the element. /// </summary> /// <param name="element">The element.</param> /// <param name="uomProperty">The uom property.</param> /// <param name="measureValue">The measure value.</param> /// <returns>The uom value if valid.</returns> /// <exception cref="WitsmlException"></exception> protected string ValidateMeasureUom(XElement element, PropertyInfo uomProperty, string measureValue) { var xmlAttribute = XmlAttributeCache <XmlAttributeAttribute> .GetCustomAttribute(uomProperty); var isRequired = IsRequired(uomProperty) && Context.Function != Functions.GetFromStore; // validation not needed if uom attribute is not defined if (xmlAttribute == null) { return(null); } var uomValue = element.Attributes() .Where(x => x.Name.LocalName == xmlAttribute.AttributeName) .Select(x => x.Value) .FirstOrDefault(); // uom is required when a measure value is specified if (isRequired && !string.IsNullOrWhiteSpace(measureValue) && string.IsNullOrWhiteSpace(uomValue)) { throw new WitsmlException(Context.Function.GetMissingUomValueErrorCode()); } return(uomValue); }
/// <summary> /// Navigates the array element. /// </summary> /// <param name="propertyInfo">The property information.</param> /// <param name="elements">The elements.</param> /// <param name="childType">Type of the child.</param> /// <param name="element">The element.</param> /// <param name="propertyPath">The property path.</param> protected virtual void NavigateArrayElementType(PropertyInfo propertyInfo, List <XElement> elements, Type childType, XElement element, string propertyPath) { var arrayItem = XmlAttributeCache <XmlArrayItemAttribute> .GetCustomAttribute(propertyInfo); // Special case when the property has both XmlArrayAttribute and XamlArrayItemAttribute // This usually indicates that XML type of the list or array has not been translated into a .NET type so // there is a mismatch between the XML type hierarchy and the .NET one. // In this case, a pseudo-property may need to be navigated, which represents the array items as a "property" on the .NET list or array type. if (arrayItem != null) { if (element.HasElements) { var childPropertyInfo = new NavigatorArrayItemPropertyInfo(propertyInfo.PropertyType, childType, arrayItem.ElementName); foreach (var childElement in element.Elements()) { NavigateElementType(childPropertyInfo, childType, childElement, GetPropertyPath(propertyPath, arrayItem.ElementName)); } } else { NavigateElementType(propertyInfo, propertyInfo.PropertyType, element, propertyPath); } } else { NavigateElementType(propertyInfo, childType, element, propertyPath); } }
private void AddMappedProperties(Type type, string path) { if (type.IsPrimitive || type.IsEnum || null == type.GetCustomAttribute <XmlTypeAttribute>()) { return; } var typeName = type.Name; var properties = type.GetProperties().Where(propertyInfo => { var elementInfo = XmlAttributeCache <XmlElementAttribute> .GetCustomAttribute(propertyInfo); var attributeInfo = XmlAttributeCache <XmlAttributeAttribute> .GetCustomAttribute(propertyInfo); var textInfo = XmlAttributeCache <XmlTextAttribute> .GetCustomAttribute(propertyInfo); return(null != elementInfo || null != attributeInfo || null != textInfo); }).ToList(); var propertiesMap = properties.ToDictionary(property => property.Name); _propertyPaths.AddRange(properties.Select(propertyInfo => $"{path}.{propertyInfo.Name}")); _propertyTypes.AddRange(properties.Select(propertyInfo => { var propertyType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; // Handle recurring element properties if (propertyType.IsGenericType && typeof(IList).IsAssignableFrom(propertyType)) { propertyType = propertyType.GetGenericArguments().First(); } return(propertyType); })); _propertyMappings[typeName] = propertiesMap; foreach (var propertyInfo in propertiesMap.Values) { var propertyType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; // Handle recurring element properties if (propertyType.IsGenericType && typeof(IList).IsAssignableFrom(propertyType)) { propertyType = propertyType.GetGenericArguments().First(); } if (type.IsPrimitive || type.IsEnum || null == propertyType.GetCustomAttribute <XmlTypeAttribute>()) { continue; } AddMappedProperties(propertyType, $"{path}.{propertyInfo.Name}"); } }
/// <summary> /// Gets the propertyinfo for the recurring element within the container. /// </summary> /// <param name="objectType">The data object type.</param> /// <param name="family">THe data object family name.</param> /// <param name="version">The version.</param> /// <returns>The recurring element propertyinfo.</returns> public static PropertyInfo GetObjectTypeListPropertyInfo(string objectType, string family, string version) { var objectGroupType = GetObjectGroupType(objectType, family, version); return(objectGroupType? .GetProperties() .Select(x => new { Property = x, Attribute = XmlAttributeCache <XmlElementAttribute> .GetCustomAttribute(x) }) .Where(x => objectType.EqualsIgnoreCase(x.Attribute?.ElementName)) .Select(x => x.Property) .FirstOrDefault()); }
/// <summary> /// Gets the property information. /// </summary> /// <param name="type">The property type.</param> /// <param name="element">An optional element containing type information.</param> /// <returns>A collection of <see cref="PropertyInfo"/> objects.</returns> protected IList <PropertyInfo> GetPropertyInfo(Type type, XElement element = null) { if (type.IsAbstract && element != null) { type = GetConcreteType(element, type); } return(type.GetProperties() .Where(p => !XmlAttributeCache <XmlIgnoreAttribute> .IsDefined(p)) .ToList()); }
/// <summary> /// Creates a <see cref="JsonProperty" /> for the given <see cref="MemberInfo" />. /// </summary> /// <param name="member">The member to create a <see cref="JsonProperty" /> for.</param> /// <param name="memberSerialization">The member's parent <see cref="MemberSerialization" />.</param> /// <returns>A created <see cref="JsonProperty" /> for the given <see cref="MemberInfo" />.</returns> protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); if (XmlAttributeCache <XmlIgnoreAttribute> .IsDefined(member)) { property.ShouldSerialize = instance => false; } return(property); }
/// <summary> /// Gets the property information for an element. /// </summary> /// <param name="properties">The properties.</param> /// <param name="name">The name of the property.</param> /// <returns>The property info for the element.</returns> protected virtual PropertyInfo GetPropertyInfoForAnElement(IList <PropertyInfo> properties, string name) { foreach (var prop in properties) { var elementAttribute = XmlAttributeCache <XmlElementAttribute> .GetCustomAttribute(prop); if (elementAttribute != null) { if (elementAttribute.ElementName.EqualsIgnoreCase(name)) { return(prop); } } var arrayAttribute = XmlAttributeCache <XmlArrayAttribute> .GetCustomAttribute(prop); if (arrayAttribute != null) { if (arrayAttribute.ElementName.EqualsIgnoreCase(name)) { return(prop); } } var attributeAttribute = XmlAttributeCache <XmlAttributeAttribute> .GetCustomAttribute(prop); if (attributeAttribute != null) { if (attributeAttribute.AttributeName.EqualsIgnoreCase(name)) { return(prop); } } // If no matches on Attributes try to match by property name if (prop.Name.EqualsIgnoreCase(name)) { return(prop); } } return(null); }
private void RemoveInvalidChildElementsAndAttributes(PropertyInfo propertyInfo, Type elementType, XElement element) { // Ignore list properties that declare child elements using XmlArrayItem if (XmlAttributeCache <XmlArrayItemAttribute> .GetCustomAttribute(propertyInfo) != null) { return; } var properties = GetPropertyInfo(elementType, element); foreach (var attribute in element.Attributes()) { if (attribute.IsNamespaceDeclaration || attribute.Name == Xsi("nil") || attribute.Name == Xsi("type")) { continue; } var attributeInfo = GetPropertyInfoForAnElement(properties, attribute.Name.LocalName); if (attributeInfo == null) { HandleInvalidAttribute(attribute); } } // Ignore CustomData child elements if (ObjectTypes.CustomData.EqualsIgnoreCase(ObjectTypes.GetObjectTypeFromGroup(element))) { return; } foreach (var child in element.Elements()) { var childInfo = GetPropertyInfoForAnElement(properties, child.Name.LocalName); if (childInfo == null) { HandleInvalidElement(child); } } }
/// <summary> /// Gets the concrete type of the element. /// </summary> /// <param name="element">The element.</param> /// <param name="propType">Type of the property.</param> /// <returns>The concrete type</returns> protected Type GetConcreteType(XElement element, Type propType) { var xsiType = element.Attributes() .Where(x => x.Name == Xsi("type")) .Select(x => x.Value.Split(':')) .FirstOrDefault(); var @namespace = element.Attributes() .Where(x => x.Name == Xmlns(xsiType.FirstOrDefault())) .Select(x => x.Value) .FirstOrDefault(); var typeName = xsiType.LastOrDefault(); return(propType.Assembly.GetTypes() .FirstOrDefault(t => { var xmlType = XmlAttributeCache <XmlTypeAttribute> .GetCustomAttribute(t); return ((xmlType != null && xmlType.TypeName == typeName) && (string.IsNullOrWhiteSpace(@namespace) || xmlType.Namespace == @namespace)); })); }
private XDocument CreateTemplate(Type type) { var xmlRoot = XmlAttributeCache <XmlRootAttribute> .GetCustomAttribute(type); var xmlType = XmlAttributeCache <XmlTypeAttribute> .GetCustomAttribute(type); var objectType = ObjectTypes.GetObjectType(type); var version = ObjectTypes.GetVersion(type); var attribute = "version"; if (OptionsIn.DataVersion.Version200.Equals(version)) { objectType = objectType.ToPascalCase(); attribute = "schemaVersion"; } else if (typeof(IEnergisticsCollection).IsAssignableFrom(type)) { objectType = ObjectTypes.SingleToPlural(objectType); } XNamespace ns = xmlType?.Namespace ?? xmlRoot.Namespace; var element = new XElement(ns + objectType); element.SetAttributeValue("xmlns", ns); var document = new XDocument(element); CreateTemplate(type, ns, document.Root); // Set version attribute for top level data objects if (document.Root != null && document.Root.Attributes(attribute).Any()) { document.Root.SetAttributeValue(attribute, version); } return(document); }
/// <summary> /// Gets the <see cref="EtpUri"/> for a given type namespace. /// </summary> /// <param name="type">The type from which the namespace is derived.</param> /// <returns>An <see cref="EtpUri"/> instance.</returns> public static EtpUri GetUriFamily(Type type) { var xmlType = XmlAttributeCache <XmlTypeAttribute> .GetCustomAttribute(type); if (xmlType?.Namespace?.EndsWith("commonv2") ?? false) { return(Eml210); } if (type?.Namespace == null) { return(Witsml141); } if (type.Namespace.Contains("WITSML131")) { return(Witsml131); } if (type.Namespace.Contains("WITSML200")) { return(Witsml200); } if (type.Namespace.Contains("PRODML200")) { return(Prodml200); } if (type.Namespace.Contains("RESQML210")) { return(Resqml210); } return(Witsml141); }
private bool IsIgnored(MemberInfo property) { return(XmlAttributeCache <XmlIgnoreAttribute> .IsDefined(property) || _ignored.Contains(property.Name)); }
private void CreateTemplate(Type objectType, XNamespace ns, XElement parent) { if (objectType == null || _excluded.Contains(objectType)) { return; } foreach (var property in objectType.GetProperties()) { var xmlAttribute = XmlAttributeCache <XmlAttributeAttribute> .GetCustomAttribute(property); var xmlElement = XmlAttributeCache <XmlElementAttribute> .GetCustomAttribute(property); var xmlArray = XmlAttributeCache <XmlArrayAttribute> .GetCustomAttribute(property); if ((xmlAttribute == null && xmlElement == null && xmlArray == null) || _excluded.Contains(property.PropertyType) || _ignored.Contains(xmlAttribute?.AttributeName) || _ignored.Contains(xmlElement?.ElementName) || IsIgnored(property)) { continue; } // Attributes if (xmlAttribute != null) { var attribute = new XAttribute(xmlAttribute.AttributeName, string.Empty); parent.Add(attribute); continue; } // Arrays if (xmlArray != null) { var xmlArrayItem = XmlAttributeCache <XmlArrayItemAttribute> .GetCustomAttribute(property); var array = new XElement(ns + xmlArray.ElementName, new XElement(ns + xmlArrayItem.ElementName)); parent.Add(array); continue; } // Elements var element = new XElement(ns + xmlElement.ElementName); parent.Add(element); var xmlComponent = XmlAttributeCache <ComponentElementAttribute> .GetCustomAttribute(property); var xmlRecurring = XmlAttributeCache <RecurringElementAttribute> .GetCustomAttribute(property); // Stop processing if not a complex type or recurring element if (xmlComponent == null && xmlRecurring == null) { continue; } var propertyType = property.PropertyType; if (propertyType.IsGenericType) { var genericDefinition = propertyType.GetGenericTypeDefinition(); if (genericDefinition == typeof(Nullable <>)) { propertyType = Nullable.GetUnderlyingType(propertyType); } else if (genericDefinition == typeof(List <>)) { propertyType = propertyType.GetGenericArguments()[0]; } } else if (objectType.IsAbstract) { propertyType = objectType.Assembly.GetTypes() .FirstOrDefault(x => !x.IsAbstract && objectType.IsAssignableFrom(x)); } CreateTemplate(propertyType, ns, element); } }
/// <summary> /// Determines whether the specified property information is required. /// </summary> /// <param name="propertyInfo">The property information.</param> /// <returns><c>true</c> if the propertyInfo has the custom attribute RequiredAttribute; /// otherwise, <c>false</c>.</returns> protected virtual bool IsRequired(PropertyInfo propertyInfo) { return(XmlAttributeCache <RequiredAttribute> .GetCustomAttribute(propertyInfo) != null); }