public void ReadXml()
        {
            AnswerCollection anss = new AnswerCollection();

            // this test checks some answer XML generated by browser interviews. It was problematic originally because of its empty <RptValue> elements
            // (expressed as paired open/close elements with nothing between them, rather than single elements with open/close combined in the same element)
            anss.ReadXml(@"<?xml version=""1.0"" standalone=""yes""?>
<AnswerSet title="""" version=""1.1"" useMangledNames=""false"">
	<Answer name=""Editor Full Name"">
		<TextValue unans=""true"" />
	</Answer>
	<Answer name=""Author Full Name"">
		<RptValue>
			<RptValue>
				<TextValue>A</TextValue>
				<TextValue unans=""true"" />
			</RptValue>
			<RptValue></RptValue>
		</RptValue>
	</Answer>
	<Answer name=""Book Title"">
		<RptValue>
			<RptValue>
				<RptValue>
					<TextValue>A</TextValue>
					<TextValue unans=""true"" />
				</RptValue>
				<RptValue></RptValue>
			</RptValue>
			<RptValue></RptValue>
		</RptValue>
	</Answer>
	<Answer name=""Date Completed"">
		<DateValue unans=""true"" />
	</Answer>
</AnswerSet>
");
            Assert.IsTrue(anss.AnswerCount == 4);
            Answer ans;

            Assert.IsFalse(anss.TryGetAnswer("Editor Full Name", Sdk.ValueType.Number, out ans));

            Assert.IsTrue(anss.TryGetAnswer("Editor Full Name", Sdk.ValueType.Text, out ans));
            Assert.IsFalse(ans.IsRepeated);
            Assert.IsTrue(ans.Save);
            Assert.IsTrue(ans.UserExtendible);
            Assert.IsTrue(ans.Type == Sdk.ValueType.Text);
            Assert.IsFalse(ans.GetAnswered());
            Assert.IsFalse(ans.GetValue <TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>().Type == Sdk.ValueType.Text);
            Assert.IsTrue(ans.GetValue <TextValue>().UserModifiable);

            Assert.IsFalse(anss.TryGetAnswer("author full name", Sdk.ValueType.Text, out ans));

            Assert.IsTrue(anss.TryGetAnswer("Author Full Name", Sdk.ValueType.Text, out ans));
            Assert.IsTrue(ans.IsRepeated);
            Assert.IsTrue(ans.GetChildCount() == 1);
            Assert.IsTrue(ans.GetChildCount(0) == 1);
            Assert.IsTrue(ans.GetChildCount(1) == 0);
            Assert.IsTrue(ans.GetValue <TextValue>(0, 0).Value == "A");
            Assert.IsFalse(ans.GetValue <TextValue>(0, 1).IsAnswered);
            Assert.IsFalse(ans.GetValue <TextValue>(1).IsAnswered);
            Assert.IsFalse(ans.GetValue <TextValue>(1, 0).IsAnswered);
            // unusual HotDocs indexing rules
            Assert.IsTrue(ans.GetValue <TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>().Value == "A");
            Assert.IsTrue(ans.GetValue <TextValue>(0).IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>(0).Value == "A");
            Assert.IsTrue(ans.GetValue <TextValue>(0, 0, 0).IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>(0, 0, 0).Value == "A");

            Assert.IsFalse(anss.TryGetAnswer("does not exist", Sdk.ValueType.Text, out ans));
        }
        public void ReadXml()
        {
            AnswerCollection anss = new AnswerCollection();
            // this test checks some answer XML generated by browser interviews. It was problematic originally because of its empty <RptValue> elements
            // (expressed as paired open/close elements with nothing between them, rather than single elements with open/close combined in the same element)
            anss.ReadXml(@"<?xml version=""1.0"" standalone=""yes""?>
            <AnswerSet title="""" version=""1.1"" useMangledNames=""false"">
            <Answer name=""Editor Full Name"">
            <TextValue unans=""true"" />
            </Answer>
            <Answer name=""Author Full Name"">
            <RptValue>
            <RptValue>
                <TextValue>A</TextValue>
                <TextValue unans=""true"" />
            </RptValue>
            <RptValue></RptValue>
            </RptValue>
            </Answer>
            <Answer name=""Book Title"">
            <RptValue>
            <RptValue>
                <RptValue>
                    <TextValue>A</TextValue>
                    <TextValue unans=""true"" />
                </RptValue>
                <RptValue></RptValue>
            </RptValue>
            <RptValue></RptValue>
            </RptValue>
            </Answer>
            <Answer name=""Date Completed"">
            <DateValue unans=""true"" />
            </Answer>
            </AnswerSet>
            ");
            Assert.IsTrue(anss.AnswerCount == 4);
            Answer ans;
            Assert.IsTrue(anss.TryGetAnswer("Editor Full Name", out ans));
            Assert.IsFalse(ans.IsRepeated);
            Assert.IsTrue(ans.Save);
            Assert.IsTrue(ans.UserExtendible);
            Assert.IsTrue(ans.Type == Sdk.ValueType.Text);
            Assert.IsFalse(ans.GetAnswered());
            Assert.IsFalse(ans.GetValue<TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>().Type == Sdk.ValueType.Text);
            Assert.IsTrue(ans.GetValue<TextValue>().UserModifiable);

            Assert.IsFalse(anss.TryGetAnswer("author full name", out ans));

            Assert.IsTrue(anss.TryGetAnswer("Author Full Name", out ans));
            Assert.IsTrue(ans.IsRepeated);
            Assert.IsTrue(ans.GetChildCount() == 1);
            Assert.IsTrue(ans.GetChildCount(0) == 1);
            Assert.IsTrue(ans.GetChildCount(1) == 0);
            Assert.IsTrue(ans.GetValue<TextValue>(0, 0).Value == "A");
            Assert.IsFalse(ans.GetValue<TextValue>(0, 1).IsAnswered);
            Assert.IsFalse(ans.GetValue<TextValue>(1).IsAnswered);
            Assert.IsFalse(ans.GetValue<TextValue>(1, 0).IsAnswered);
            // unusual HotDocs indexing rules
            Assert.IsTrue(ans.GetValue<TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>().Value == "A");
            Assert.IsTrue(ans.GetValue<TextValue>(0).IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>(0).Value == "A");
            Assert.IsTrue(ans.GetValue<TextValue>(0, 0, 0).IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>(0, 0, 0).Value == "A");

            Assert.IsFalse(anss.TryGetAnswer("does not exist", out ans));
        }
Beispiel #3
0
        private static void LoadAnswerFileDataSource(AnswerFileDataSource answerFileDataSource)
        {
            Debug.Assert(s_readerWriterLock.IsWriteLockHeld);

            Stream answerFileStream = null;

            try
            {
                answerFileStream = new FileStream(answerFileDataSource.AnswerFilePath, FileMode.Open, FileAccess.Read);

                AnswerCollection answerSet = new AnswerCollection();
                answerSet.ReadXml(answerFileStream);

                ResourceSet   resourceSet  = s_metadata.ResourceSets.Single(rs => rs.Name == answerFileDataSource.ResourceId);
                ResourceType  resourceType = resourceSet.ResourceType;
                List <Answer> answers      = new List <Answer>(resourceType.Properties.Count);
                int           repeatCount  = 0;
                Answer        answer;
                foreach (var property in resourceType.Properties)
                {
                    if (((property.Kind & ResourcePropertyKind.Key) != ResourcePropertyKind.Key) &&
                        answerSet.TryGetAnswer(answerFileDataSource.PropertyNameToSourceNameMap[property.Name], out answer))
                    {
                        // Sanity check to be sure the property type the metadata is expecting is the same as the values in the answer file.
                        Type type;
                        switch (answer.Type)
                        {
                        case ValueType.Text:
                        case ValueType.MultipleChoice:
                            type = typeof(string);
                            break;

                        case ValueType.Number:
                            type = typeof(double?);
                            break;

                        case ValueType.Date:
                            type = typeof(DateTime?);
                            break;

                        case ValueType.TrueFalse:
                            type = typeof(bool?);
                            break;

                        default:
                            throw new Exception(string.Format("The value type '{0}' is not supported.", answer.Type.ToString()));
                        }

                        if (property.ResourceType.InstanceType != type)
                        {
                            throw new Exception(string.Format("The type of the metadata property '{0}' does not match the type of the " +
                                                              "corresponding answer '{1}'.", answerFileDataSource.PropertyNameToSourceNameMap[property.Name], answer.Name));
                        }

                        repeatCount = Math.Max(repeatCount, answer.GetChildCount());
                        answers.Add(answer);
                    }
                    else
                    {
                        answers.Add(null);
                    }
                }

                // Populate the data source with data.
                IList <DSPResource> resourceList = s_context.GetResourceSetEntities(resourceSet.Name);
                resourceList.Clear();

                for (int repeatIndex = 0; repeatIndex < repeatCount; repeatIndex++)
                {
                    var resource = new DSPResource(resourceSet.ResourceType, s_readerWriterLock);

                    for (int propertyIndex = 0; propertyIndex < resourceType.Properties.Count; propertyIndex++)
                    {
                        ResourceProperty property = resourceType.Properties[propertyIndex];
                        object           value;
                        if ((property.Kind & ResourcePropertyKind.Key) == ResourcePropertyKind.Key)
                        {
                            value = repeatIndex + 1;
                        }
                        else
                        {
                            IValue iValue = null;
                            answer = answers[propertyIndex];
                            if ((answer != null) && (repeatIndex <= answer.GetChildCount()))
                            {
                                iValue = answer.GetValue(repeatIndex);
                            }

                            if (property.ResourceType.InstanceType == typeof(string))
                            {
                                value = ((iValue != null) && iValue.IsAnswered) ? iValue.ToString(null) : string.Empty;
                            }
                            else if (property.ResourceType.InstanceType == typeof(double?))
                            {
                                if ((iValue != null) && iValue.IsAnswered)
                                {
                                    value = iValue.ToDouble(null);
                                }
                                else
                                {
                                    value = null;
                                }
                            }
                            else if (property.ResourceType.InstanceType == typeof(DateTime?))
                            {
                                if ((iValue != null) && iValue.IsAnswered)
                                {
                                    value = iValue.ToDateTime(null);
                                }
                                else
                                {
                                    value = null;
                                }
                            }
                            else
                            {
                                Debug.Assert(property.ResourceType.InstanceType == typeof(bool?));
                                if ((iValue != null) && iValue.IsAnswered)
                                {
                                    value = iValue.ToBoolean(null);
                                }
                                else
                                {
                                    value = null;
                                }
                            }
                        }

                        resource.SetValue(property.Name, value);
                    }

                    resourceList.Add(resource);
                }
            }
            catch (Exception e)
            {
                throw new DataServiceException(string.Format("Failed to read the answers for the data source key '{0}' from the answer file '{1}'.",
                                                             answerFileDataSource.DataSourceId, answerFileDataSource.DataSourceName), e);
            }
            finally
            {
                if (answerFileStream != null)
                {
                    answerFileStream.Close();
                }
            }
        }
Beispiel #4
0
        public void ReadXml()
        {
            AnswerCollection anss = new AnswerCollection();

            // this test checks some answer XML generated by browser interviews. It was problematic originally because of its empty <RptValue> elements
            // (expressed as paired open/close elements with nothing between them, rather than single elements with open/close combined in the same element)
            // NOTE: added a lot of oddly formed and malformed answers to this answer collection, for purposes of
            // trying to ensure that we read answer XML in a more robust manner.  Some 3rd parties generate XML
            // that is schema valid, but is otherwise (by HotDocs standards) quite odd.  For example, answers marked
            // "unanswered" but which have answer data present, or which use collapsed XML elements in ways
            // HotDocs typically does not.
            anss.ReadXml(@"<?xml version=""1.0"" standalone=""yes""?>
<AnswerSet title="""" version=""1.1"" useMangledNames=""false"">
	<Answer name=""Editor Full Name"">
		<TextValue unans=""true"" />
	</Answer>
	<Answer name=""Text000"">
		<TextValue/>
	</Answer>
	<Answer name=""Text010"">
		<TextValue></TextValue>
	</Answer>
	<Answer name=""Text020"">
		<TextValue>Test Answer</TextValue>
	</Answer>
	<Answer name=""Text030"">
		<TextValue>
    Another
Test Answer
        </TextValue>
	</Answer>
	<Answer name=""Text040"">
		<TextValue unans=""true""></TextValue>
	</Answer>
	<Answer name=""Text050"">
		<TextValue unans=""true"">An Invalid Test Answer</TextValue>
	</Answer>
	<Answer name=""Number000"">
		<NumValue/>
	</Answer>
	<Answer name=""Number010"">
		<NumValue unans=""true"" />
	</Answer>
	<Answer name=""Number020"">
		<NumValue unans=""true""></NumValue>
	</Answer>
	<Answer name=""Number030"">
		<NumValue>5.0000000</NumValue>
	</Answer>
	<Answer name=""Number040"">
		<NumValue>123</NumValue>
	</Answer>
	<Answer name=""Number050"">
		<NumValue unans=""true"">234 or anything else</NumValue>
	</Answer>
	<Answer name=""Date000"">
		<DateValue/>
	</Answer>
	<Answer name=""Date010"">
		<DateValue></DateValue>
	</Answer>
	<Answer name=""Date020"">
		<DateValue unans=""true"" />
	</Answer>
	<Answer name=""Date030"">
		<DateValue unans=""true"" ></DateValue>
	</Answer>
	<Answer name=""Date Completed"">
		<DateValue>31-10-2015</DateValue>
	</Answer>
	<Answer name=""TF000"">
		<TFValue/>
	</Answer>
	<Answer name=""TF010"">
		<TFValue></TFValue>
	</Answer>
	<Answer name=""TF020"">
		<TFValue unans=""true"" />
	</Answer>
	<Answer name=""TF030"">
		<TFValue unans=""true""></TFValue>
	</Answer>
	<Answer name=""TF040"">
		<TFValue>true</TFValue>
	</Answer>
	<Answer name=""TF050"">
		<TFValue unans=""false"">False</TFValue>
	</Answer>
	<Answer name=""TF060"">
		<TFValue unans=""true"">Ignored</TFValue>
	</Answer>
    <Answer name=""MCVar000"">
        <MCValue/>
    </Answer>
    <Answer name=""MCVar010"">
        <MCValue unans=""true"" />
    </Answer>
    <Answer name=""MCVar020"">
        <MCValue></MCValue>
    </Answer>
    <Answer name=""MCVar030"">
        <MCValue unans=""true""></MCValue>
    </Answer>
    <Answer name=""MCVar031"">
        <MCValue>
            <SelValue/>
        </MCValue>
    </Answer>
    <Answer name=""MCVar032"">
        <MCValue unans=""true"">
            <SelValue unans=""true""/>
        </MCValue>
    </Answer>
    <Answer name=""MCVar033"">
        <MCValue unans=""true"">
            <SelValue></SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar034"">
        <MCValue unans=""true"">
            <SelValue unans=""true""></SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar035"">
        <MCValue unans=""true"">
            <SelValue>sel1</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar040"">
        <MCValue>
            <SelValue/>
        </MCValue>
    </Answer>
    <Answer name=""MCVar050"">
        <MCValue>
            <SelValue unans=""true""/>
        </MCValue>
    </Answer>
    <Answer name=""MCVar060"">
        <MCValue>
            <SelValue></SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar070"">
        <MCValue>
            <SelValue unans=""true""></SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar080"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue>sel2</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar090"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue></SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar100"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue/>
        </MCValue>
    </Answer>
    <Answer name=""MCVar110"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""></SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar120"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""/>
        </MCValue>
    </Answer>
    <Answer name=""MCVar130"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue></SelValue>
            <SelValue>sel3</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar140"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue/>
            <SelValue>sel3</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar150"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""></SelValue>
            <SelValue>sel3</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar160"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""/>
            <SelValue>sel3</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar170"">
        <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true"">sel2</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar180"">
        <MCValue>
            <SelValue unans=""true"">sel1</SelValue>
            <SelValue unans=""true"">sel2</SelValue>
        </MCValue>
    </Answer>
    <Answer name=""MCVar190"">
        <MCValue>
            <SelValue unans=""true"">sel1</SelValue>
            <SelValue>sel2</SelValue>
        </MCValue>
    </Answer>
	<Answer name=""Author Full Name"">
		<RptValue>
			<RptValue>
				<TextValue>A</TextValue>
				<TextValue unans=""true"" />
			</RptValue>
			<RptValue></RptValue>
		</RptValue>
	</Answer>
	<Answer name=""Book Title"">
		<RptValue>
			<RptValue>
				<RptValue>
					<TextValue>A</TextValue>
					<TextValue unans=""true"" />
				</RptValue>
				<RptValue></RptValue>
			</RptValue>
			<RptValue></RptValue>
		</RptValue>
	</Answer>
</AnswerSet>
");
            Assert.IsTrue(anss.AnswerCount == 52);
            Answer ans;

            // ensure that lookup of incorrect typed answer fails
            Assert.IsFalse(anss.TryGetAnswer("Editor Full Name", Sdk.ValueType.Number, out ans));

            // test various attributes of an answer
            Assert.IsTrue(anss.TryGetAnswer("Editor Full Name", Sdk.ValueType.Text, out ans));
            Assert.IsFalse(ans.IsRepeated);
            Assert.IsTrue(ans.Save);
            Assert.IsTrue(ans.UserExtendible);
            Assert.IsTrue(ans.Type == Sdk.ValueType.Text);
            Assert.IsFalse(ans.GetAnswered());
            Assert.IsFalse(ans.GetValue <TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>().Type == Sdk.ValueType.Text);
            Assert.IsTrue(ans.GetValue <TextValue>().UserModifiable);

            // ensure lookup of name with incorrect casing fails
            Assert.IsFalse(anss.TryGetAnswer("author full name", Sdk.ValueType.Text, out ans));

            // check some repeated answer indexing rules
            Assert.IsTrue(anss.TryGetAnswer("Author Full Name", Sdk.ValueType.Text, out ans));
            Assert.IsTrue(ans.IsRepeated);
            Assert.IsTrue(ans.GetChildCount() == 1);
            Assert.IsTrue(ans.GetChildCount(0) == 1);
            Assert.IsTrue(ans.GetChildCount(1) == 0);
            Assert.IsTrue(ans.GetValue <TextValue>(0, 0).Value == "A");
            Assert.IsFalse(ans.GetValue <TextValue>(0, 1).IsAnswered);
            Assert.IsFalse(ans.GetValue <TextValue>(1).IsAnswered);
            Assert.IsFalse(ans.GetValue <TextValue>(1, 0).IsAnswered);
            // unusual HotDocs indexing rules
            Assert.IsTrue(ans.GetValue <TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>().Value == "A");
            Assert.IsTrue(ans.GetValue <TextValue>(0).IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>(0).Value == "A");
            Assert.IsTrue(ans.GetValue <TextValue>(0, 0, 0).IsAnswered);
            Assert.IsTrue(ans.GetValue <TextValue>(0, 0, 0).Value == "A");

            // ensure that lookup of non-existing answer fails
            Assert.IsFalse(anss.TryGetAnswer("does not exist", Sdk.ValueType.Text, out ans));
        }
        public void ReadXml()
        {
            AnswerCollection anss = new AnswerCollection();
            // this test checks some answer XML generated by browser interviews. It was problematic originally because of its empty <RptValue> elements
            // (expressed as paired open/close elements with nothing between them, rather than single elements with open/close combined in the same element)
            // NOTE: added a lot of oddly formed and malformed answers to this answer collection, for purposes of
            // trying to ensure that we read answer XML in a more robust manner.  Some 3rd parties generate XML
            // that is schema valid, but is otherwise (by HotDocs standards) quite odd.  For example, answers marked
            // "unanswered" but which have answer data present, or which use collapsed XML elements in ways
            // HotDocs typically does not.
            anss.ReadXml(@"<?xml version=""1.0"" standalone=""yes""?>
            <AnswerSet title="""" version=""1.1"" useMangledNames=""false"">
            <Answer name=""Editor Full Name"">
            <TextValue unans=""true"" />
            </Answer>
            <Answer name=""Text000"">
            <TextValue/>
            </Answer>
            <Answer name=""Text010"">
            <TextValue></TextValue>
            </Answer>
            <Answer name=""Text020"">
            <TextValue>Test Answer</TextValue>
            </Answer>
            <Answer name=""Text030"">
            <TextValue>
            Another
            Test Answer
            </TextValue>
            </Answer>
            <Answer name=""Text040"">
            <TextValue unans=""true""></TextValue>
            </Answer>
            <Answer name=""Text050"">
            <TextValue unans=""true"">An Invalid Test Answer</TextValue>
            </Answer>
            <Answer name=""Number000"">
            <NumValue/>
            </Answer>
            <Answer name=""Number010"">
            <NumValue unans=""true"" />
            </Answer>
            <Answer name=""Number020"">
            <NumValue unans=""true""></NumValue>
            </Answer>
            <Answer name=""Number030"">
            <NumValue>5.0000000</NumValue>
            </Answer>
            <Answer name=""Number040"">
            <NumValue>123</NumValue>
            </Answer>
            <Answer name=""Number050"">
            <NumValue unans=""true"">234 or anything else</NumValue>
            </Answer>
            <Answer name=""Date000"">
            <DateValue/>
            </Answer>
            <Answer name=""Date010"">
            <DateValue></DateValue>
            </Answer>
            <Answer name=""Date020"">
            <DateValue unans=""true"" />
            </Answer>
            <Answer name=""Date030"">
            <DateValue unans=""true"" ></DateValue>
            </Answer>
            <Answer name=""Date Completed"">
            <DateValue>31-10-2015</DateValue>
            </Answer>
            <Answer name=""TF000"">
            <TFValue/>
            </Answer>
            <Answer name=""TF010"">
            <TFValue></TFValue>
            </Answer>
            <Answer name=""TF020"">
            <TFValue unans=""true"" />
            </Answer>
            <Answer name=""TF030"">
            <TFValue unans=""true""></TFValue>
            </Answer>
            <Answer name=""TF040"">
            <TFValue>true</TFValue>
            </Answer>
            <Answer name=""TF050"">
            <TFValue unans=""false"">False</TFValue>
            </Answer>
            <Answer name=""TF060"">
            <TFValue unans=""true"">Ignored</TFValue>
            </Answer>
            <Answer name=""MCVar000"">
            <MCValue/>
            </Answer>
            <Answer name=""MCVar010"">
            <MCValue unans=""true"" />
            </Answer>
            <Answer name=""MCVar020"">
            <MCValue></MCValue>
            </Answer>
            <Answer name=""MCVar030"">
            <MCValue unans=""true""></MCValue>
            </Answer>
            <Answer name=""MCVar031"">
            <MCValue>
            <SelValue/>
            </MCValue>
            </Answer>
            <Answer name=""MCVar032"">
            <MCValue unans=""true"">
            <SelValue unans=""true""/>
            </MCValue>
            </Answer>
            <Answer name=""MCVar033"">
            <MCValue unans=""true"">
            <SelValue></SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar034"">
            <MCValue unans=""true"">
            <SelValue unans=""true""></SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar035"">
            <MCValue unans=""true"">
            <SelValue>sel1</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar040"">
            <MCValue>
            <SelValue/>
            </MCValue>
            </Answer>
            <Answer name=""MCVar050"">
            <MCValue>
            <SelValue unans=""true""/>
            </MCValue>
            </Answer>
            <Answer name=""MCVar060"">
            <MCValue>
            <SelValue></SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar070"">
            <MCValue>
            <SelValue unans=""true""></SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar080"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue>sel2</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar090"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue></SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar100"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue/>
            </MCValue>
            </Answer>
            <Answer name=""MCVar110"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""></SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar120"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""/>
            </MCValue>
            </Answer>
            <Answer name=""MCVar130"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue></SelValue>
            <SelValue>sel3</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar140"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue/>
            <SelValue>sel3</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar150"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""></SelValue>
            <SelValue>sel3</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar160"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true""/>
            <SelValue>sel3</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar170"">
            <MCValue>
            <SelValue>sel1</SelValue>
            <SelValue unans=""true"">sel2</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar180"">
            <MCValue>
            <SelValue unans=""true"">sel1</SelValue>
            <SelValue unans=""true"">sel2</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""MCVar190"">
            <MCValue>
            <SelValue unans=""true"">sel1</SelValue>
            <SelValue>sel2</SelValue>
            </MCValue>
            </Answer>
            <Answer name=""Author Full Name"">
            <RptValue>
            <RptValue>
                <TextValue>A</TextValue>
                <TextValue unans=""true"" />
            </RptValue>
            <RptValue></RptValue>
            </RptValue>
            </Answer>
            <Answer name=""Book Title"">
            <RptValue>
            <RptValue>
                <RptValue>
                    <TextValue>A</TextValue>
                    <TextValue unans=""true"" />
                </RptValue>
                <RptValue></RptValue>
            </RptValue>
            <RptValue></RptValue>
            </RptValue>
            </Answer>
            </AnswerSet>
            ");
            Assert.IsTrue(anss.AnswerCount == 52);
            Answer ans;

            // ensure that lookup of incorrect typed answer fails
            Assert.IsFalse(anss.TryGetAnswer("Editor Full Name", Sdk.ValueType.Number, out ans));

            // test various attributes of an answer
            Assert.IsTrue(anss.TryGetAnswer("Editor Full Name", Sdk.ValueType.Text, out ans));
            Assert.IsFalse(ans.IsRepeated);
            Assert.IsTrue(ans.Save);
            Assert.IsTrue(ans.UserExtendible);
            Assert.IsTrue(ans.Type == Sdk.ValueType.Text);
            Assert.IsFalse(ans.GetAnswered());
            Assert.IsFalse(ans.GetValue<TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>().Type == Sdk.ValueType.Text);
            Assert.IsTrue(ans.GetValue<TextValue>().UserModifiable);

            // ensure lookup of name with incorrect casing fails
            Assert.IsFalse(anss.TryGetAnswer("author full name", Sdk.ValueType.Text, out ans));

            // check some repeated answer indexing rules
            Assert.IsTrue(anss.TryGetAnswer("Author Full Name", Sdk.ValueType.Text, out ans));
            Assert.IsTrue(ans.IsRepeated);
            Assert.IsTrue(ans.GetChildCount() == 1);
            Assert.IsTrue(ans.GetChildCount(0) == 1);
            Assert.IsTrue(ans.GetChildCount(1) == 0);
            Assert.IsTrue(ans.GetValue<TextValue>(0, 0).Value == "A");
            Assert.IsFalse(ans.GetValue<TextValue>(0, 1).IsAnswered);
            Assert.IsFalse(ans.GetValue<TextValue>(1).IsAnswered);
            Assert.IsFalse(ans.GetValue<TextValue>(1, 0).IsAnswered);
            // unusual HotDocs indexing rules
            Assert.IsTrue(ans.GetValue<TextValue>().IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>().Value == "A");
            Assert.IsTrue(ans.GetValue<TextValue>(0).IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>(0).Value == "A");
            Assert.IsTrue(ans.GetValue<TextValue>(0, 0, 0).IsAnswered);
            Assert.IsTrue(ans.GetValue<TextValue>(0, 0, 0).Value == "A");

            // ensure that lookup of non-existing answer fails
            Assert.IsFalse(anss.TryGetAnswer("does not exist", Sdk.ValueType.Text, out ans));
        }
        private static void LoadAnswerFileDataSource(AnswerFileDataSource answerFileDataSource)
        {
            Debug.Assert(s_readerWriterLock.IsWriteLockHeld);

            Stream answerFileStream = null;

            try
            {
                answerFileStream = new FileStream(answerFileDataSource.AnswerFilePath, FileMode.Open, FileAccess.Read);

                AnswerCollection answerSet = new AnswerCollection();
                answerSet.ReadXml(answerFileStream);

                ResourceSet   resourceSet  = s_metadata.ResourceSets.Single(rs => rs.Name == answerFileDataSource.ResourceId);
                ResourceType  resourceType = resourceSet.ResourceType;
                List <Answer> answers      = new List <Answer>(resourceType.Properties.Count);
                int           repeatCount  = 0;
                Answer        answer;
                foreach (var property in resourceType.Properties)
                {
                    if ((property.Kind & ResourcePropertyKind.Key) != ResourcePropertyKind.Key)
                    {
                        ValueType valueType = ValueType.Unknown;

                        // Infer from the CLR type what the ValueType is of the answer to be fetched.
                        if (property.ResourceType.InstanceType == typeof(string))
                        {
                            valueType = ValueType.Text;
                        }
                        else if (property.ResourceType.InstanceType == typeof(double?))
                        {
                            valueType = ValueType.Number;
                        }
                        else if (property.ResourceType.InstanceType == typeof(DateTime?))
                        {
                            valueType = ValueType.Date;
                        }
                        else if (property.ResourceType.InstanceType == typeof(bool?))
                        {
                            valueType = ValueType.TrueFalse;
                        }

                        if (valueType == ValueType.Unknown)
                        {
                            throw new Exception(string.Format("The metadata property '{0}' with a CLR type of '{1}' does not correspond to a supported " +
                                                              "HotDocs ValueType.", answerFileDataSource.PropertyNameToSourceNameMap[property.Name],
                                                              property.ResourceType.InstanceType.FullName));
                        }

                        if (answerSet.TryGetAnswer(answerFileDataSource.PropertyNameToSourceNameMap[property.Name], valueType, out answer) ||
                            ((valueType == ValueType.Text) &&
                             answerSet.TryGetAnswer(answerFileDataSource.PropertyNameToSourceNameMap[property.Name], ValueType.MultipleChoice, out answer)))
                        {
                            repeatCount = Math.Max(repeatCount, answer.GetChildCount());
                            answers.Add(answer);
                        }
                        else
                        {
                            answers.Add(null);
                        }
                    }
                }

                // Populate the data source with data.
                IList <DSPResource> resourceList = s_context.GetResourceSetEntities(resourceSet.Name);
                resourceList.Clear();

                for (int repeatIndex = 0; repeatIndex < repeatCount; repeatIndex++)
                {
                    var resource    = new DSPResource(resourceSet.ResourceType, s_readerWriterLock);
                    int answerIndex = 0;
                    for (int propertyIndex = 0; propertyIndex < resourceType.Properties.Count; propertyIndex++)
                    {
                        ResourceProperty property = resourceType.Properties[propertyIndex];
                        object           value;
                        if ((property.Kind & ResourcePropertyKind.Key) == ResourcePropertyKind.Key)
                        {
                            value = repeatIndex + 1;
                        }
                        else
                        {
                            IValue iValue = null;
                            answer = answers[answerIndex++];
                            if ((answer != null) && (repeatIndex <= answer.GetChildCount()))
                            {
                                iValue = answer.GetValue(repeatIndex);
                            }

                            if (property.ResourceType.InstanceType == typeof(string))
                            {
                                value = ((iValue != null) && iValue.IsAnswered) ? iValue.ToString(null) : string.Empty;
                            }
                            else if (property.ResourceType.InstanceType == typeof(double?))
                            {
                                if ((iValue != null) && iValue.IsAnswered)
                                {
                                    value = iValue.ToDouble(null);
                                }
                                else
                                {
                                    value = null;
                                }
                            }
                            else if (property.ResourceType.InstanceType == typeof(DateTime?))
                            {
                                if ((iValue != null) && iValue.IsAnswered)
                                {
                                    value = iValue.ToDateTime(null);
                                }
                                else
                                {
                                    value = null;
                                }
                            }
                            else
                            {
                                Debug.Assert(property.ResourceType.InstanceType == typeof(bool?));
                                if ((iValue != null) && iValue.IsAnswered)
                                {
                                    value = iValue.ToBoolean(null);
                                }
                                else
                                {
                                    value = null;
                                }
                            }
                        }

                        resource.SetValue(property.Name, value);
                    }

                    resourceList.Add(resource);
                }
            }
            catch (Exception e)
            {
                throw new DataServiceException(string.Format("Failed to read the answers for the data source key '{0}' from the answer file '{1}'.",
                                                             answerFileDataSource.DataSourceId, answerFileDataSource.DataSourceName), e);
            }
            finally
            {
                if (answerFileStream != null)
                {
                    answerFileStream.Close();
                }
            }
        }