Ejemplo n.º 1
0
        /// <summary>
        /// Parses an instance of the specified type from the specified stream
        /// </summary>
        public object Parse(System.Xml.XmlReader s, Type useType, Type currentInteractionType, XmlIts1FormatterParseResult resultContext)
        {

            ConstructorInfo ci = useType.GetConstructor(Type.EmptyTypes);
            if(ci == null)
                throw new InvalidOperationException(String.Format("Cannot create an instance of type '{0}' as it defines no default constructor", useType.FullName));

            // Create the instance
            object instance = ci.Invoke(null);

            PropertyInfo[] properties = useType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            // Move the reader to the first attribute
            if (s.MoveToFirstAttribute())
            {
                // Now we read the attributes and match with the properties
                do
                {



#if WINDOWS_PHONE
                    PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0);
#else
                    PropertyInfo pi = Array.Find<PropertyInfo>(properties, o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0);
#endif              
                    // Can we set the PI?
                    if (s.LocalName == "ITSVersion" && s.Value != "XML_1.0")
                        throw new System.InvalidOperationException(System.String.Format("This formatter can only parse XML_1.0 structures. This structure claims to be '{0}'.", s.Value));
                    else if (s.Prefix == "xmlns" || s.LocalName == "xmlns" || s.LocalName == "ITSVersion" || s.NamespaceURI == XmlIts1Formatter.NS_XSI)
                        continue;
                    else if (pi == null)
                    {
                        resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, String.Format("@{0}", s.LocalName), s.NamespaceURI, s.ToString(), null));
                        continue;
                    }

                    var paList = pi.GetCustomAttributes(typeof(PropertyAttribute), true); // property attributes
                    
                    // VAlidate list of PA
                    if(paList == null || paList.Length != 1)
                    {
                        resultContext.AddResultDetail(new ResultDetail(ResultDetailType.Warning, String.Format("Invalid number of PropertyAttributes on property '{0}', ignoring", pi.Name), s.ToString(), null));
                        continue; // not a property to be parsed
                    }

                    if (pi.GetSetMethod() == null)
                    {
                        if (!Util.ToWireFormat(pi.GetValue(instance, null)).Equals(s.Value))
                            resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, pi.GetValue(instance, null).ToString(), true, s.ToString()));
                    }
                    else if (!String.IsNullOrEmpty((paList[0] as PropertyAttribute).FixedValue))
                    {
                        if (!(paList[0] as PropertyAttribute).FixedValue.Equals(s.Value))
                        {
                            resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, (paList[0] as PropertyAttribute).FixedValue, false, s.ToString()));
                            pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null);
                        }
                    }
                    else
                        pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null);
                }
                while (s.MoveToNextAttribute());
                s.MoveToElement();
            }

            // Nil? 
            // BUG: Fixed, xsi:nil may also have a null-flavor
            String nil = s.GetAttribute("nil", XmlIts1Formatter.NS_XSI);
            if (!String.IsNullOrEmpty(nil) && Convert.ToBoolean(nil))
                return instance;


            // Is reader at an empty element
            if (s.IsEmptyElement) return instance;

            // Read content
            string currentElementName = s.LocalName,
                lastElementRead = s.LocalName;
            while(true)
            {

                // End of stream or item not read
                if (lastElementRead == s.LocalName && !s.Read())
                    break;

                lastElementRead = s.LocalName;

                // Element is end element and matches the starting element namd
                if (s.NodeType == System.Xml.XmlNodeType.EndElement && s.LocalName == currentElementName)
                    break;
                // Element is an end element
                //else if (s.NodeType == System.Xml.XmlNodeType.EndElement)
                //    currentDepth--;
                // Element is a start element
                else if (s.NodeType == System.Xml.XmlNodeType.Element)
                {
                    // Get the element choice property
#if WINDOWS_PHONE
                    PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(a => 
                        a is PropertyAttribute && 
                        (a as PropertyAttribute).Name == s.LocalName && 
                        ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0);
#else
                    PropertyInfo pi = Array.Find(properties, o => o.GetCustomAttributes(true).Count(a => 
                        a is PropertyAttribute && 
                        (a as PropertyAttribute).Name == s.LocalName && 
                        ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0);
#endif
                    if (pi == null)
                    {
                        resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, s.LocalName, s.NamespaceURI, s.ToString(), null));
                        continue;
                    }

                    // Get the property attribute that defined the choice
#if WINDOWS_PHONE
                    PropertyAttribute pa = pi.GetCustomAttributes(true).Find(p => 
                        p is PropertyAttribute && 
                        (p as PropertyAttribute).Name == s.LocalName && 
                        ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute;
#else
                    PropertyAttribute pa = Array.Find(pi.GetCustomAttributes(true), p => 
                        p is PropertyAttribute && 
                        (p as PropertyAttribute).Name == s.LocalName && 
                        ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute;
#endif
                    // Can we set the PI?
                    if (pi == null || !pi.CanWrite) continue;

                    // Now time to set the PI
                    if (String.IsNullOrEmpty(s.GetAttribute("specializationType")) && s is MARC.Everest.Xml.XmlStateReader && (this.Host.Settings & SettingsType.AllowFlavorImposing) == SettingsType.AllowFlavorImposing) (s as MARC.Everest.Xml.XmlStateReader).AddFakeAttribute("specializationType", pa.ImposeFlavorId);

                    // Cannot deserialize this
                    if (pa.Type == null && pi.PropertyType == typeof(System.Object))
                        resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, pi.Name, pa.NamespaceUri, s.ToString(), null));
                    // Simple deserialization if PA type has IGraphable or PI type has IGraphable and PA type not specified
                    else if (pi.GetSetMethod() != null &&
                        (pa.Type != null && pa.Type.GetInterface(typeof(IGraphable).FullName, false) != null) ||
                        (pa.Type == null && pi.PropertyType.GetInterface(typeof(IGraphable).FullName, false) != null))
                    {
                        object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext);
                        if (!String.IsNullOrEmpty(pa.FixedValue) && !pa.FixedValue.Equals(Util.ToWireFormat(tempFormat)) && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable)
                            resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(Util.ToWireFormat(tempFormat), pa.FixedValue, s.ToString()));
                        pi.SetValue(instance, Util.FromWireFormat(tempFormat, pa.Type ?? pi.PropertyType), null);
                    }
                    // Call an Add method on a collection type
                    else if (pi.PropertyType.GetMethod("Add") != null) // Collection type
                        pi.PropertyType.GetMethod("Add").Invoke(pi.GetValue(instance, null), new object[] { 
                            Util.FromWireFormat(Host.ParseObject(s, pi.PropertyType.GetGenericArguments()[0], currentInteractionType, resultContext), pi.PropertyType.GetGenericArguments()[0])
                        });
                    // Call the ParseXML custom function on object
                    else if (pi.GetSetMethod() != null && pi.PropertyType.GetMethod("ParseXml", BindingFlags.Public | BindingFlags.Static) != null)
                        pi.SetValue(instance, pi.PropertyType.GetMethod("ParseXml").Invoke(instance, new object[] { s }), null);
                    // Property type is a simple string
                    else if (pi.GetSetMethod() != null && pi.PropertyType == typeof(string)) // Read content... 
                        pi.SetValue(instance, Util.FromWireFormat(s.ReadInnerXml(), typeof(String)), null);
                    // No Set method is used, fixed value?
                    else
                    {
                        object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext);
                        if (tempFormat.ToString() != pi.GetValue(instance, null).ToString() && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable)
                            resultContext.AddResultDetail(new MARC.Everest.Connectors.FixedValueMisMatchedResultDetail(tempFormat.ToString(), pi.GetValue(instance, null).ToString(), s.ToString()));
                    }

                }
            }
            
            return instance;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Parses an instance of the specified type from the specified stream
        /// </summary>
        public object Parse(System.Xml.XmlReader s, Type useType, Type currentInteractionType, XmlIts1FormatterParseResult resultContext)
        {
            ConstructorInfo ci = useType.GetConstructor(Type.EmptyTypes);

            if (ci == null)
            {
                throw new InvalidOperationException(String.Format("Cannot create an instance of type '{0}' as it defines no default constructor", useType.FullName));
            }

            // Create the instance
            object instance = ci.Invoke(null);

            PropertyInfo[] properties = useType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            // Move the reader to the first attribute
            if (s.MoveToFirstAttribute())
            {
                // Now we read the attributes and match with the properties
                do
                {
#if WINDOWS_PHONE
                    PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0);
#else
                    PropertyInfo pi = Array.Find <PropertyInfo>(properties, o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0);
#endif
                    // Can we set the PI?
                    if (s.LocalName == "ITSVersion" && s.Value != "XML_1.0")
                    {
                        throw new System.InvalidOperationException(System.String.Format("This formatter can only parse XML_1.0 structures. This structure claims to be '{0}'.", s.Value));
                    }
                    else if (s.Prefix == "xmlns" || s.LocalName == "xmlns" || s.LocalName == "ITSVersion" || s.NamespaceURI == XmlIts1Formatter.NS_XSI)
                    {
                        continue;
                    }
                    else if (pi == null)
                    {
                        resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, String.Format("@{0}", s.LocalName), s.NamespaceURI, s.ToString(), null));
                        continue;
                    }

                    var paList = pi.GetCustomAttributes(typeof(PropertyAttribute), true); // property attributes

                    // VAlidate list of PA
                    if (paList == null || paList.Length != 1)
                    {
                        resultContext.AddResultDetail(new ResultDetail(ResultDetailType.Warning, String.Format("Invalid number of PropertyAttributes on property '{0}', ignoring", pi.Name), s.ToString(), null));
                        continue; // not a property to be parsed
                    }

                    if (pi.GetSetMethod() == null)
                    {
                        if (!Util.ToWireFormat(pi.GetValue(instance, null)).Equals(s.Value))
                        {
                            resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, pi.GetValue(instance, null).ToString(), true, s.ToString()));
                        }
                    }
                    else if (!String.IsNullOrEmpty((paList[0] as PropertyAttribute).FixedValue))
                    {
                        if (!(paList[0] as PropertyAttribute).FixedValue.Equals(s.Value))
                        {
                            resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, (paList[0] as PropertyAttribute).FixedValue, false, s.ToString()));
                            pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null);
                        }
                    }
                    else
                    {
                        pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null);
                    }
                }while (s.MoveToNextAttribute());
                s.MoveToElement();
            }

            // Nil?
            // BUG: Fixed, xsi:nil may also have a null-flavor
            String nil = s.GetAttribute("nil", XmlIts1Formatter.NS_XSI);
            if (!String.IsNullOrEmpty(nil) && Convert.ToBoolean(nil))
            {
                return(instance);
            }


            // Is reader at an empty element
            if (s.IsEmptyElement)
            {
                return(instance);
            }

            // Read content
            string currentElementName = s.LocalName,
                   lastElementRead    = s.LocalName;
            while (true)
            {
                // End of stream or item not read
                if (lastElementRead == s.LocalName && !s.Read())
                {
                    break;
                }

                lastElementRead = s.LocalName;

                // Element is end element and matches the starting element namd
                if (s.NodeType == System.Xml.XmlNodeType.EndElement && s.LocalName == currentElementName)
                {
                    break;
                }
                // Element is an end element
                //else if (s.NodeType == System.Xml.XmlNodeType.EndElement)
                //    currentDepth--;
                // Element is a start element
                else if (s.NodeType == System.Xml.XmlNodeType.Element)
                {
                    // Get the element choice property
#if WINDOWS_PHONE
                    PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(a =>
                                                                                             a is PropertyAttribute &&
                                                                                             (a as PropertyAttribute).Name == s.LocalName &&
                                                                                             ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0);
#else
                    PropertyInfo pi = Array.Find(properties, o => o.GetCustomAttributes(true).Count(a =>
                                                                                                    a is PropertyAttribute &&
                                                                                                    (a as PropertyAttribute).Name == s.LocalName &&
                                                                                                    ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0);
#endif
                    if (pi == null)
                    {
                        resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, s.LocalName, s.NamespaceURI, s.ToString(), null));
                        continue;
                    }

                    // Get the property attribute that defined the choice
#if WINDOWS_PHONE
                    PropertyAttribute pa = pi.GetCustomAttributes(true).Find(p =>
                                                                             p is PropertyAttribute &&
                                                                             (p as PropertyAttribute).Name == s.LocalName &&
                                                                             ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute;
#else
                    PropertyAttribute pa = Array.Find(pi.GetCustomAttributes(true), p =>
                                                      p is PropertyAttribute &&
                                                      (p as PropertyAttribute).Name == s.LocalName &&
                                                      ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute;
#endif
                    // Can we set the PI?
                    if (pi == null || !pi.CanWrite)
                    {
                        continue;
                    }

                    // Now time to set the PI
                    if (String.IsNullOrEmpty(s.GetAttribute("specializationType")) && s is MARC.Everest.Xml.XmlStateReader && (this.Host.Settings & SettingsType.AllowFlavorImposing) == SettingsType.AllowFlavorImposing)
                    {
                        (s as MARC.Everest.Xml.XmlStateReader).AddFakeAttribute("specializationType", pa.ImposeFlavorId);
                    }

                    // Cannot deserialize this
                    if (pa.Type == null && pi.PropertyType == typeof(System.Object))
                    {
                        resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, pi.Name, pa.NamespaceUri, s.ToString(), null));
                    }
                    // Simple deserialization if PA type has IGraphable or PI type has IGraphable and PA type not specified
                    else if (pi.GetSetMethod() != null &&
                             (pa.Type != null && pa.Type.GetInterface(typeof(IGraphable).FullName, false) != null) ||
                             (pa.Type == null && pi.PropertyType.GetInterface(typeof(IGraphable).FullName, false) != null))
                    {
                        object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext);
                        if (!String.IsNullOrEmpty(pa.FixedValue) && !pa.FixedValue.Equals(Util.ToWireFormat(tempFormat)) && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable)
                        {
                            resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(Util.ToWireFormat(tempFormat), pa.FixedValue, s.ToString()));
                        }
                        pi.SetValue(instance, Util.FromWireFormat(tempFormat, pa.Type ?? pi.PropertyType), null);
                    }
                    // Call an Add method on a collection type
                    else if (pi.PropertyType.GetMethod("Add") != null) // Collection type
                    {
                        pi.PropertyType.GetMethod("Add").Invoke(pi.GetValue(instance, null), new object[] {
                            Util.FromWireFormat(Host.ParseObject(s, pi.PropertyType.GetGenericArguments()[0], currentInteractionType, resultContext), pi.PropertyType.GetGenericArguments()[0])
                        });
                    }
                    // Call the ParseXML custom function on object
                    else if (pi.GetSetMethod() != null && pi.PropertyType.GetMethod("ParseXml", BindingFlags.Public | BindingFlags.Static) != null)
                    {
                        pi.SetValue(instance, pi.PropertyType.GetMethod("ParseXml").Invoke(instance, new object[] { s }), null);
                    }
                    // Property type is a simple string
                    else if (pi.GetSetMethod() != null && pi.PropertyType == typeof(string)) // Read content...
                    {
                        pi.SetValue(instance, Util.FromWireFormat(s.ReadInnerXml(), typeof(String)), null);
                    }
                    // No Set method is used, fixed value?
                    else
                    {
                        object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext);
                        if (tempFormat.ToString() != pi.GetValue(instance, null).ToString() && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable)
                        {
                            resultContext.AddResultDetail(new MARC.Everest.Connectors.FixedValueMisMatchedResultDetail(tempFormat.ToString(), pi.GetValue(instance, null).ToString(), s.ToString()));
                        }
                    }
                }
            }

            return(instance);
        }