Example #1
0
        public static XmlDocument BuildRamsellXmlDocForFormResult(int formResultId, IFormsRepository formsRepo)
        {
            string       xsdFilePath = HttpContext.Current.Server.MapPath(xsdPath);
            XmlSchemaSet schemaSet   = Utilities.GetXsdSchemaSet(xsdFilePath);

            // Extract the schema sets from the XSD (microsoft actually does it this way)
            // https://msdn.microsoft.com/en-us/library/ms255932(v=vs.110).aspx
            XmlSchema schema = null;

            foreach (XmlSchema xs in schemaSet.Schemas())
            {
                schema = xs;
            }

            // convert schema heirarchy into custom types. See "SchemaElement" and subclasses below.
            // (the ResponseElement subclass will be used to link "leaf" nodes with item variables)
            List <RamsellExport.DefSchemaElement> defElements = RamsellExport.ParseSchemaElements(schema.Elements.Values);

            // build response xml document based on schema
            XmlDocument outputXmlDoc = new XmlDocument();

            // Removed schemaSet from top level tag per Ramsell
            // outputXmlDoc.Schemas.Add(schemaSet);
            //outputXmlDoc.AppendChild(outputXmlDoc.CreateComment("Responses taken from formResult " + formResultId));
            foreach (RamsellExport.DefSchemaElement elem in defElements)
            {
                RamsellExport.BuildResponseXml(null, outputXmlDoc, elem, formResultId, formsRepo);
            }

            // Validate response xml based on schema
            // resultDoc.Validate((object sender, ValidationEventArgs args) => { throw new Exception(args.Message); } );
            try
            {
                Debug.WriteLine("XSD resultDoc.Schemas.Count: " + outputXmlDoc.Schemas.Count.ToString());

                /*
                 * foreach (System.Xml.Schema.XmlSchemaSet xss in resultDoc.Schemas.Schemas())
                 * {
                 *  Debug.WriteLine("XSD Schemas NameTable: " + xss.NameTable.ToString());
                 * }
                 */
                ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
                outputXmlDoc.Validate(eventHandler);
                Debug.WriteLine("*** Validation is complete.");
            }
            catch (Exception xcptn)
            {
                Debug.WriteLine("Validate exception: " + xcptn.Message);
            }

            return(outputXmlDoc);
        }
        /// <summary>
        /// Process a single node from an XML improted from Ramsell, modifying the specified formResult as applicable.
        /// Noramlly this will only be called from within a loop to iterate over xml nodes, however this function will recurse to handle Ramsell's "income" structures
        /// </summary>
        /// <param name="fromReader">XmlReader where Read() has already been called</param>
        /// <param name="checkedBoxes">this should ba appended to with itemVariable identifiers for each checked checkbox. Used to uncheck excluded boxes at the end of the import</param>
        /// <param name="specialCaseValuesByTagname">this will be used to run special-case transformations that may involve multiple ramsell tags</param>
        private void ImportXmlNodeFromRamsell(
            XmlReader fromReader,
            List <string> checkedBoxes,
            Dictionary <string, string> specialCaseValuesByTagname)
        {
            if (fromReader.NodeType != XmlNodeType.Element)
            {
                throw new Exception("Expecting NodeType \"" + XmlNodeType.Element + "\", found \"" + fromReader.NodeType + "\"");
            }
            string ramellTagName = fromReader.Name;

            //the "Income_Item" tag is a one-off structure with multiple occurances
            if (ramellTagName == "Income_Item")
            {
                ImportIncomeStructureFromRamsell(fromReader);
                return;
            }

            //get the nodes contents
            string ramsellVal = String.Empty;

            if (!fromReader.IsEmptyElement)
            {
                fromReader.Read();
                if (fromReader.NodeType == XmlNodeType.EndElement)
                {
                    return;
                }
                if (fromReader.NodeType != XmlNodeType.Text)
                {
                    throw new Exception("Inside of node \"" + ramellTagName + "\", found NodeType \"" + fromReader.NodeType
                                        + "\", expecting NodeType \"" + XmlNodeType.Text + "\", or \"" + XmlNodeType.EndElement + "\"");
                }
                ramsellVal = fromReader.Value;
            }


            //based on tagName, check if this a simple case (no transformation necessary)
            List <string> ivIdentifiers = RamsellExport.GetItemVariableIdentifiersForRamsellTagName(ramellTagName);

            if (ivIdentifiers.Count == 1)
            {
                //one-to-one case: this ramsell tagName corresponds with exactly one itemVariable
                //so just save the text contents as a response to that itemVariable

                // RRB 4/18/16 Ramsell seems to be sending a default date of 1900-01-01
                //              This should be tested more.  If doesn't fix, maybe our date converter is causing an empty DOB to be this date.
                if (ramellTagName.Equals("DOB") && (string.IsNullOrEmpty(ramsellVal) || ramsellVal.StartsWith("1900")))
                {
                    ;
                }
                else
                {
                    UpdateResponse(ivIdentifiers[0], ramsellVal);
                }
            }
            else if (ivIdentifiers.Count > 1)
            {
                //checkbox case: this ramsell tagName corresponds to a set of itemVariables (representing checkboxes in the application)
                //so pick the checkbox based on this node's text contents, and save the response "1" for that checkbox
                #region checkbox case

                //based on lookups, pick the inidividual itemvariable (matchIv) that matches the node contents (ramsellVal)
                def_ItemVariables matchIv = null;
                foreach (string ivIdent in ivIdentifiers)
                {
                    def_ItemVariables iv = formsRepo.GetItemVariableByIdentifier(ivIdent);
                    if (iv.baseTypeId == 1)
                    {
                        def_LookupMaster lm = formsRepo.GetLookupMastersByLookupCode(iv.identifier);
                        if (lm != null)
                        {
                            List <def_LookupDetail> ld = formsRepo.GetLookupDetailsByLookupMasterEnterprise(lm.lookupMasterId, SessionHelper.LoginStatus.EnterpriseID);
                            if (ld.Where(ldt => ramsellVal == ldt.dataValue).Any())
                            {
                                matchIv = iv;
                                break;
                            }
                        }
                    }
                }

                //save the respones "1" to the single matched itemVariable, and add it to the "checkedBoxes" list
                //at the end of the import, any grouped checkboxes that haven't been added to that list will be unchecked
                if (matchIv == null)
                {
                    Debug.WriteLine("* * * RamsellImport: Could not find matching itemVariable for ramsell tag/value \"" + ramellTagName + "/" + ramsellVal + "\", skipping...");
                }
                else
                {
                    def_ItemResults ir = userData.SaveItemResult(toFormResultId, matchIv.itemId);
                    userData.SaveResponseVariable(ir, matchIv, "1");
                    checkedBoxes.Add(matchIv.identifier);
                }
                #endregion
            }
            else
            {
                //this tagname must be either ignorable or handled by a special one-off transformation,
                //so just record the tagname/value pair to be handled later on.
                //the special-cases can involve multiple ramsell tags so there is no way to handle them one tag at a time.
                specialCaseValuesByTagname.Add(ramellTagName, ramsellVal);
            }
        }