예제 #1
0
        /// <summary>
        /// Creates an XmlElement representing an Epi Info 7 view's data.
        /// </summary>
        /// <param name="xmlDataPackage">The data package xml document that the XmlElement should be added to</param>
        /// <param name="form">The form whose data will be serialized</param>
        /// <returns>XmlElement; represents the form's data in Xml format, suitable for use in data packaging</returns>
        protected XmlElement CreateXmlFormDataElement(XmlDocument xmlDataPackage, View form)
        {
            #region Input Validation
            if (xmlDataPackage == null)
            {
                throw new ArgumentNullException("xmlDataPackage");
            }
            if (form == null)
            {
                throw new ArgumentNullException("form");
            }
            #endregion // Input Validation

            XmlElement data = xmlDataPackage.CreateElement("Data");

            if (StatusChanged != null)
            {
                StatusChanged(string.Format(PackagerStrings.GUID_LIST_SETUP, form.Name));
            }
            if (ResetProgress != null)
            {
                ResetProgress();
            }

            /* This seems like an usual set of steps to just iterate over the data. The problem is that we can't "just
             * iterate over the data" - the data is split up page tables, with one table representing one page on the
             * form. While a JOIN might be able to bring everything together into one table, it might not - for example,
             * if there are >255 fields after the JOIN, an OleDb exception will be thrown.
             *
             * To get around this issue: The code first iterates over the rows in the BASE TABLE, obtaining the GUID
             * values for each. The GUIDs and their corresponding XmlElement go into a dictionary.
             *
             * Later, each row in each page is iterated over; as the GUIDs for each page table are accessed, the corresponding
             * XmlElement is pulled from the dictionary. Field data is added to it for each field that has data. In this
             * manner, it doesn't matter that each row is technically accessed out-of-order because they'll still show up
             * in-order in the resulting Xml.
             *
             * Filtering adds another layer of complexity. To filter, a JOIN operation is needed so that the filters can
             * be applied across all those tables, since the fields in the filter may be across different tables. The
             * RowFilter class provides a way to handle this; we simply get the query from that object and apply it to the
             * reader. Only GUIDs that match the filter are added to the dictionary of guids.
             */

            // We need to exclude records from child forms that may now be orphaned as a result of a filter applied to the parent
            if (form.IsRelatedView && PreviousDistanceFromRoot < CurrentDistanceFromRoot)
            {
                ParentIdList.Clear();
                foreach (KeyValuePair <string, XmlElement> kvp in IdList)
                {
                    ParentIdList.Add(kvp.Key);
                }
            }

            IdList.Clear(); // Very important, this needs to be re-set in case we've already processed a form (this is a class level variable)

            if (!ExportInfo.RecordsPackaged.ContainsKey(form))
            {
                ExportInfo.RecordsPackaged.Add(form, 0);
            }

            bool       filterThisForm = false;
            RowFilters filters        = null;
            Query      selectQuery    = null;

            if (Filters != null && Filters.ContainsKey(form.Name) && Filters[form.Name].Count() > 0)
            {
                filterThisForm = true;
                filters        = Filters[form.Name];
                selectQuery    = filters.GetGuidSelectQuery(form);
            }

            double totalRecords = 0;

            using (IDataReader guidReader = filterThisForm ? SourceProject.CollectedData.GetDatabase().ExecuteReader(selectQuery) : SourceProject.CollectedData.GetDatabase().GetTableDataReader(form.TableName))
            {
                while (guidReader.Read())
                {
                    string   guid            = guidReader["GlobalRecordId"].ToString();
                    string   fkey            = guidReader["FKEY"].ToString();
                    string   recstatus       = guidReader["RECSTATUS"].ToString();
                    string   firstSaveUserId = string.Empty;
                    DateTime?firstSaveTime   = null;
                    string   lastSaveUserId  = string.Empty;
                    DateTime?lastSaveTime    = null;

                    if (guidReader.FieldCount > 3)
                    {
                        try
                        {
                            firstSaveUserId = guidReader["FirstSaveLogonName"].ToString();
                            if (guidReader["FirstSaveTime"] != DBNull.Value)
                            {
                                firstSaveTime = (DateTime)guidReader["FirstSaveTime"];
                            }
                            lastSaveUserId = guidReader["LastSaveLogonName"].ToString();
                            if (guidReader["LastSaveTime"] != DBNull.Value)
                            {
                                lastSaveTime = (DateTime)guidReader["LastSaveTime"];
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            // just ignore, probably an older upgraded project
                        }
                    }

                    if (recstatus.Equals("1")) // only include undeleted records
                    {
                        if (!form.IsRelatedView || ParentIdList.Contains(fkey))
                        {
                            XmlElement   record = xmlDataPackage.CreateElement("Record");
                            XmlAttribute id     = xmlDataPackage.CreateAttribute("Id");
                            id.Value = guid;
                            record.Attributes.Append(id);

                            if (!string.IsNullOrEmpty(fkey))
                            {
                                XmlAttribute foreignKey = xmlDataPackage.CreateAttribute("Fkey");
                                foreignKey.Value = fkey;
                                record.Attributes.Append(foreignKey);
                            }
                            if (!string.IsNullOrEmpty(firstSaveUserId))
                            {
                                XmlAttribute firstSaveId = xmlDataPackage.CreateAttribute("FirstSaveUserId");
                                firstSaveId.Value = firstSaveUserId;
                                record.Attributes.Append(firstSaveId);
                            }
                            if (!string.IsNullOrEmpty(lastSaveUserId))
                            {
                                XmlAttribute lastSaveId = xmlDataPackage.CreateAttribute("LastSaveUserId");
                                lastSaveId.Value = lastSaveUserId;
                                record.Attributes.Append(lastSaveId);
                            }
                            if (firstSaveTime.HasValue)
                            {
                                XmlAttribute firstSaveDateTime = xmlDataPackage.CreateAttribute("FirstSaveTime");
                                firstSaveDateTime.Value = firstSaveTime.Value.Ticks.ToString();
                                record.Attributes.Append(firstSaveDateTime);
                            }
                            if (lastSaveTime.HasValue)
                            {
                                XmlAttribute lastSaveDateTime = xmlDataPackage.CreateAttribute("LastSaveTime");
                                lastSaveDateTime.Value = lastSaveTime.Value.Ticks.ToString();
                                record.Attributes.Append(lastSaveDateTime);
                            }
                            IdList.Add(guid, record);
                            totalRecords++;

                            ExportInfo.TotalRecordsPackaged++;
                            ExportInfo.RecordsPackaged[form]++;
                        }
                    }
                }
            }

            totalRecords = totalRecords * form.Pages.Count;
            int processedRecords = 0;

            if (StatusChanged != null)
            {
                StatusChanged(string.Format(PackagerStrings.ADDING_FIELD_DATA, form.Name));
            }

            foreach (Page page in form.Pages)
            {
                using (IDataReader reader = SourceProject.CollectedData.GetDatabase().GetTableDataReader(page.TableName))
                {
                    while (reader.Read())
                    {
                        string guid = reader["GlobalRecordId"].ToString();

                        if (IdList.ContainsKey(guid))
                        {
                            XmlElement element = IdList[guid];

                            foreach (Field field in page.Fields)
                            {
                                if (field is IDataField && field is RenderableField && !(field is GridField) && !(FieldsToNull.ContainsKey(form.Name) && FieldsToNull[form.Name].Contains(field.Name)))
                                {
                                    RenderableField renderableField = field as RenderableField;
                                    if (renderableField != null)
                                    {
                                        XmlElement fieldData = xmlDataPackage.CreateElement("Field");

                                        XmlAttribute name = xmlDataPackage.CreateAttribute("Name");
                                        name.Value = renderableField.Name;
                                        fieldData.Attributes.Append(name);

                                        string value = reader[field.Name].ToString();

                                        if (!string.IsNullOrEmpty(value))
                                        {
                                            if (field is DateTimeField)
                                            {
                                                DateTime dt = Convert.ToDateTime(value);
                                                fieldData.InnerText = dt.Ticks.ToString();
                                            }
                                            else if (field is ImageField)
                                            {
                                                value = Convert.ToBase64String((Byte[])reader[field.Name]);
                                                fieldData.InnerText = value;
                                            }
                                            else
                                            {
                                                fieldData.InnerText = value;
                                            }
                                        }

                                        if (IncludeNullFieldData == false && String.IsNullOrEmpty(fieldData.InnerText))
                                        {
                                            // do nothing, for now...
                                        }
                                        else
                                        {
                                            element.AppendChild(fieldData);
                                        }
                                        data.AppendChild(element);
                                    }
                                }
                            }
                        }
                        processedRecords++;
                        double progress = (((double)processedRecords) / ((double)totalRecords)) * 100;
                        if (UpdateProgress != null)
                        {
                            UpdateProgress(progress);
                        }
                    }
                }
            }
            foreach (GridField gridField in form.Fields.GridFields)
            {
                data.AppendChild(CreateXmlGridElement(xmlDataPackage, form, gridField));
                ExportInfo.GridsProcessed++;
            }

            return(data);
        }