예제 #1
0
                /// <summary>
        /// Parses an object from <paramref name="r"/> using <paramref name="a"/> to locate
        /// a suitable class definition to populate.
        /// </summary>
        /// <param name="r">The <see cref="T:System.Xml.XmlReader"/> from which to parse the object</param>
        /// <param name="a"><paramref name="s"/> in object form</param>
        /// <returns>A <see cref="MARC.Everest.Formatters.XML.ITS1.Its1FormatterParseResult"/> containing the results of the parse</returns>
        /// <remarks>
        /// <para>This method differs from the <seealso cref="F:Parse(System.Xml.XmlReader)"/> method in that it
        /// will only look within the specified assembly for a suitable class to populate.</para>
        /// <para>
        /// This method will not check the current learned type repository for a class to serialize (ie: it will always 
        /// check the assembly regardless of what has been formatted prior)
        /// </para>
        /// </remarks>
        public IFormatterParseResult Parse(XmlReader r, Assembly a)
        {
            ThrowIfDisposed();

            var resultContext = new XmlIts1FormatterParseResult(ResultCode.Accepted, null);

            if (!(r is XmlStateReader))
                r = new XmlStateReader(r);

            // Initial state
            if (r.ReadState == ReadState.Initial)
                while (r.NodeType != XmlNodeType.Element)
                    r.Read();

            // Detect if we can parse this...
            //if (r.NamespaceURI != "urn:hl7-org:v3")
            //    throw new XmlException(string.Format("Can't parse '{0}' in namespace '{1}'. The data does not appear to be an HL7v3 instance", r.LocalName, r.NamespaceURI), null);

            // Predicate will find the mapped type for us
            Predicate<Type> typeComparator = delegate(Type t)
            {
                object[] structureAttribute = t.GetCustomAttributes(typeof(StructureAttribute), true);
                if (structureAttribute.Length > 0 && ((structureAttribute[0] as StructureAttribute).StructureType == StructureAttribute.StructureAttributeType.Interaction || (structureAttribute[0] as StructureAttribute).IsEntryPoint)
                    && (structureAttribute[0] as StructureAttribute).Name == r.LocalName && (structureAttribute[0] as StructureAttribute).NamespaceUri == r.NamespaceURI)
                    return true;
                return false;
            };

            // Try to find the value if it doesn't succeed, try to build it and try to find it again
#if WINDOWS_PHONE
            Type fType = a.GetTypes().Find(typeComparator);
#else
            Type fType = Array.Find<Type>(a.GetTypes(), typeComparator);
#endif

            // Found the type
            if (fType != null)
                resultContext.Structure = this.ParseObject(r, fType, fType, resultContext);
            else
                resultContext.AddResultDetail(
                        new ResultDetail(ResultDetailType.Error, String.Format("Could not find a type to de-serialize '{0}' into", r.Name), r.ToString(), null)
                    );

            // Set the acceptance code
            resultContext.Code = CalculateResultCode(resultContext.Details);
            return resultContext;
        }
예제 #2
0
        /// <summary>
        /// Parse an object from <see cref="T:System.Xml.XmlReader"/> <paramref name="r"/>
        /// </summary>
        /// <param name="r">The <see cref="T:System.Xml.XmlReader"/> to parse an object from</param>
        /// <returns>A <see cref="T:MARC.Everest.Formatters.XML.ITS1.Its1FormatterParseResult"/> containing the formatted instance</returns>
        /// <remarks>
        /// <para>
        /// This particular overload of the Graph method can be used to graph objects into a <see cref="T:System.Xml.XmlWriter"/> and can provide
        /// an opportunity to use Everest as an assistant (or XmlSerializerSurrogate) for more complex systems like WCF.
        /// </para>
        /// <example>
        /// <code lang="cs" title="Using Everest as a Serializer Assistant">
        /// <![CDATA[
        /// StringWriter sw = new StringWriter("<hello><MCCI_IN000002CA xmlns=\"urn:hl7-org:v3\"/></hello>");
        /// XmlReader reader = XmlReader.Create(sw);
        /// reader.Read(); // Read <hello>
        /// 
        /// Formatter f = new Formatter();
        /// f.GraphAides.Add(typeof(MARC.Everest.Formatters.XML.DataTypes.R1.Formatter));
        /// f.ValidateConformance = false;
        /// var result = f.Parse(reader);
        /// 
        /// reader.Read();
        /// reader.Close();
        /// Console.WriteLine(result.Code); 
        /// 
        /// ]]>
        /// </code>
        /// </example>
        /// <para>
        /// When using this method, it is recommended that you pass a <see cref="T:MARC.Everest.Xml.XmlStateReader"/> as it 
        /// will allow the formatter to give additional location information when reporting issues.
        /// </para>
        /// </remarks>
        public IFormatterParseResult Parse(XmlReader r)
        {
            ThrowIfDisposed();

            // Clear existing results
            XmlIts1FormatterParseResult resultContext = new XmlIts1FormatterParseResult(ResultCode.Accepted, null);

            if (!(r is XmlStateReader))
                r = new XmlStateReader(r);

            // Initial state
            if (r.ReadState == ReadState.Initial)
                while (r.NodeType != XmlNodeType.Element)
                    r.Read();

            // Detect if we can parse this...
            //if (r.NamespaceURI != "urn:hl7-org:v3")
            //    throw new XmlException(string.Format("Can't parse '{0}' in namespace '{1}'. The data does not appear to be an HL7v3 instance", r.LocalName, r.NamespaceURI), null);

            // Do we have a formatter for the object
            Type mappedType;

            // Predicate will find the mapped type for us
            Predicate<Type> typeComparator = delegate(Type t)
            {
                object[] structureAttribute = t.GetCustomAttributes(typeof(StructureAttribute), true);
                if (structureAttribute.Length > 0 && ((structureAttribute[0] as StructureAttribute).StructureType == StructureAttribute.StructureAttributeType.Interaction || (structureAttribute[0] as StructureAttribute).IsEntryPoint)
                    && (structureAttribute[0] as StructureAttribute).Name == r.LocalName && (structureAttribute[0] as StructureAttribute).NamespaceUri == r.NamespaceURI)
                    return true;
                return false;
            };

            // Try to find the value if it doesn't succeed, try to build it and try to find it again
            for (int i = 0; i < 2 && resultContext.Structure == null; i++)
            {
                if (s_rootNameMaps.TryGetValue(r.LocalName, out mappedType)) // Try to get a root name map
                {
                    resultContext.Structure = ParseObject(r, mappedType, mappedType, resultContext);
                    resultContext.Code = CalculateResultCode(resultContext.Details);
                    return resultContext;
                }
                else if (i == 0) // Try to build the cache for this root name
                {
                    // Last attempt, try to find a type in the app domain that we can scan!
                    Predicate<Assembly> asmPredicate = delegate(Assembly a)
                    {
                        try
                        {
#if WINDOWS_PHONE
                            return a.GetTypes().Exists(typeComparator);
#else
                            return Array.Find<Type>(a.GetTypes(), typeComparator) != null;
#endif
                        }
                        catch
                        {
                            return false;
                        }
                    };

#if WINDOWS_PHONE
                    Assembly asm = AppDomain.CurrentDomain.GetAssemblies().Find(asmPredicate);
#else
                    Assembly asm = Array.Find<Assembly>(AppDomain.CurrentDomain.GetAssemblies(), asmPredicate);
#endif
                    if (asm == null) // Couldn't find assembly... ditch
                        break;
                    else
                        return Parse(r, asm); //BuildCache(new Type[] { Array.Find<Type>(asm.GetTypes(), typeComparator) });
                }
                //i++;
            }

            resultContext.AddResultDetail(new ResultDetail(ResultDetailType.Error, String.Format("Could not find a type to de-serialize '{0}' into", r.Name), r.ToString(), null));
            resultContext.Code = ResultCode.Rejected;
            return resultContext;
        }
예제 #3
0
        /// <summary>
        /// Parse an object from <see cref="T:System.Xml.XmlReader"/> <paramref name="r"/> using the type
        /// hint <param name="t"/>
        /// </summary>
        /// <param name="r">The <see cref="T:System.Xml.XmlReader"/> to parse an object from</param>
        /// <param name="t">The type hint to parse the object</param>
        /// <returns>A <see cref="T:MARC.Everest.Formatters.XML.ITS1.Its1FormatterParseResult"/> containing the formatted instance</returns>
        /// <remarks>
        /// <para>
        /// This particular overload of the Graph method can be used to graph objects into a <see cref="T:System.Xml.XmlWriter"/> and can provide
        /// an opportunity to use Everest as an assistant (or XmlSerializerSurrogate) for more complex systems like WCF.
        /// </para>
        /// <example>
        /// <code lang="cs" title="Using Everest as a Serializer Assistant">
        /// <![CDATA[
        /// StringWriter sw = new StringWriter("<hello><MCCI_IN000002CA xmlns=\"urn:hl7-org:v3\"/></hello>");
        /// XmlReader reader = XmlReader.Create(sw);
        /// reader.Read(); // Read <hello>
        /// 
        /// Formatter f = new Formatter();
        /// f.GraphAides.Add(typeof(MARC.Everest.Formatters.XML.DataTypes.R1.Formatter));
        /// f.ValidateConformance = false;
        /// var result = f.Parse(reader, typeof(MCCI_IN000002CA));
        /// 
        /// reader.Read();
        /// reader.Close();
        /// Console.WriteLine(result.Code); 
        /// 
        /// ]]>
        /// </code>
        /// </example>
        /// <para>
        /// When using this method, it is recommended that you pass a <see cref="T:MARC.Everest.Xml.XmlStateReader"/> as it 
        /// will allow the formatter to give additional location information when reporting issues.
        /// </para>
        /// </remarks>
        public IFormatterParseResult Parse(XmlReader r, Type t)
        {
            if (!(r is XmlStateReader))
                r = new XmlStateReader(r);

            // Initial state
            if (r.ReadState == ReadState.Initial)
                while (r.NodeType != XmlNodeType.Element)
                    r.Read();

            // Detect if we can parse this...
            if (r.NamespaceURI != "urn:hl7-org:v3")
                throw new XmlException(string.Format("Can't parse '{0}' in namespace '{1}'. The data does not appear to be an HL7v3 instance", r.LocalName, r.NamespaceURI), null);

            var resultContext = new XmlIts1FormatterParseResult(ResultCode.Accepted, null);
            resultContext.Structure = ParseObject(r, t, null, resultContext);
            return resultContext;
        }
예제 #4
0
        public virtual IGraphable ParseObject(XmlReader r, Type useType, Type interactionContext, XmlIts1FormatterParseResult resultContext)
        {
            ThrowIfDisposed();


            // Find a helper
            string typeName = GetStructureName(useType);

            IXmlStructureFormatter ixsf = null;
            
            // xsi type? - We want to adjust the type based on this value
            try
            {
                string xsiType = r.GetAttribute("type", NS_XSI);
                // Is this model / type registered somewhere ?
                if ((this.Settings & SettingsType.AlwaysCheckForOverrides) != 0 && xsiType == null &&
                    !typeof(ANY).IsAssignableFrom(useType))
                    xsiType = this.CreateXSITypeName(useType, interactionContext, r as IXmlNamespaceResolver);

                if (xsiType != null)
                {
                    if (useType.IsInterface || typeof(ANY).IsAssignableFrom(useType)) // HACK: We don't override the use type for ANY derivatives as some types are special and require special typing
                        ixsf = this.GetAdjustedFormatter(xsiType); //Util.ParseXSITypeName(r.GetAttribute("type", NS_XSI));
                    else
                        useType = this.ParseXSITypeName(xsiType, r as IXmlNamespaceResolver);
                }
                else
                    ixsf = (IXmlStructureFormatter)this.GraphAides.Find(t => t.HandleStructure.Contains(typeName));
            }
            catch (Exception e)
            {
                resultContext.AddResultDetail(new ResultDetail(ResultDetailType.Error, e.Message, r.ToString(), e));
            }

            string currentPath = r is XmlStateReader ? (r as XmlStateReader).CurrentPath : r.Name;
            // Does a helper have it?
            if (ixsf != null)
            {
                ixsf.Host = this;
                var aideResult = ixsf.Parse(r, useType);
                resultContext.AddResultDetail(aideResult.Details);
                return aideResult.Structure;
            }

#if WINDOWS_PHONE
            ITypeFormatter formatter = m_codeGeneratorFormatter.GetFormatter(useType);
            if (formatter == null)
                formatter = new ReflectFormatter();
#else
            ITypeFormatter formatter = m_codeGeneratorFormatter.GetFormatter(useType);
            // Is there a formatter and if there is not a formatter 
            // can we create one?
            if (formatter == null && (Settings & SettingsType.UseGeneratorFormat) == SettingsType.UseGeneratorFormat)
                s_threadPool.QueueUserWorkItem((WaitCallback)delegate(object state)
                {
                    BuildCache(new Type[] { (Type)state });
                }, useType);
            // If there is no connector can we use reflection?
            if (formatter == null && (Settings & SettingsType.UseReflectionFormat) == SettingsType.UseReflectionFormat)
                formatter = new ReflectFormatter();
            else if (formatter == null && (Settings & SettingsType.UseGeneratorFormat) == SettingsType.UseGeneratorFormat)
            {
                s_threadPool.WaitOne();
                formatter = m_codeGeneratorFormatter.GetFormatter(useType);
            }
#endif
            if (formatter == null)
                throw new InvalidOperationException(string.Format("Couldn't format '{0}' at {1}, verify formatter settings", useType.FullName, r.ToString()));

            // Parse using the formatter
            formatter.Host = this;

            // Parse the object
            IGraphable result = (IGraphable)formatter.Parse(r, useType, interactionContext, resultContext);

            IResultDetail[] details = null;
            if (details != null && result == null || ValidateConformance && (!formatter.Validate(result, currentPath, out details)))
                resultContext.AddResultDetail(details.Length > 0 ? details : new IResultDetail[] { new ResultDetail(ValidateConformance ? ResultDetailType.Error : ResultDetailType.Warning, String.Format("Couldn't parse type '{0}'", useType.ToString()), currentPath) });

            
            return result;
        }