Ejemplo n.º 1
0
            // private recursive helper function
            private ValueNode <T> GetNodeHelper(ValueNode <T> node, int atDepth, bool createIfNecessary, bool valuesBubbleAndFlow, int[] rptIdx)
            {
                // this can be invoked with the following flag combinations:
                //     createIfNecessary == true   &&   valuesBubbleAndFlow == true   // we will be setting an answer
                //     createIfNecessary == false  &&   valuesBubbleAndFlow == true   // we will be getting an answer
                //     createIfNecessary == false  &&   valuesBubbleAndFlow == false  // we are looking up a node to count or manipulate its children

                // if we're recursing deeper than the _depth of this answer, we should not be creating nodes as we go!
                // (In that case, ValueNode<T>.Expand should have been called first to push values down the tree as necessary.)
                Debug.Assert(atDepth <= Depth || !createIfNecessary);

                if (node == null)
                {
                    throw new ArgumentNullException("node");
                }
                if (rptIdx == null)
                {
                    throw new ArgumentNullException("rptIdx");
                }

                // see if we're done recursing through all the repeat levels
                if (rptIdx.Length == 0 && atDepth == Depth)
                {
                    ValueNode <T> result = node;
                    if (valuesBubbleAndFlow)
                    {
                        // if we've found a node but it still has children in the tree,
                        // then the value from a 0-indexed descendant node will "bubble up".
                        while (result.HasChildren)
                        {
                            result = result.Children[0];
                        }
                    }
                    return(result);
                }

                int idx;

                int[] newIdx;
                if (rptIdx.Length > 0)
                {
                    idx = rptIdx[0];
                    // continue recursing down through the repeat levels
                    newIdx = new int[rptIdx.Length - 1];
                    if (rptIdx.Length > 1)
                    {
                        Array.Copy(rptIdx, 1, newIdx, 0, newIdx.Length);
                    }
                }
                else                 // rptIdx.Length == 0 ... we've run out of repeat indices
                {
                    Debug.Assert(atDepth < Depth);
                    if (valuesBubbleAndFlow)                     // create new, zero indices so we can continue recursion
                    {
                        idx    = 0;
                        newIdx = new int[Depth - atDepth - 1];                         // make sure value gets set down at the appropriate repeat level
                    }
                    else
                    {
                        Debug.Assert(!createIfNecessary);                         // we don't want to allow setting values at non-leaf nodes of the tree!
                        return(node);
                    }
                }

                // there are still repeat indices through which to recurse...
                if (createIfNecessary)                 // expand current node as necessary
                {
                    if (!node.HasChildren)
                    {
                        node.Expand(1, true);
                    }
                    if (idx >= node.Children.SetCount)
                    {
                        node.Children.PrepareForIndex(idx);
                    }
                }
                else if (!node.HasChildren)
                {
                    // requested node does not exist -- given indexes exceed depth of repeated values
                    return((valuesBubbleAndFlow && idx == 0 && RepeatIndices.IsFirst(newIdx)) ? node : null);
                }
                else if (idx >= node.Children.SetCount)
                {
                    // requested node does not exist -- given indexes exceed number of repeated values
                    return(null);
                }

                return(GetNodeHelper(node.Children[idx], ++atDepth, createIfNecessary, valuesBubbleAndFlow, newIdx));
            }
Ejemplo n.º 2
0
        private void ReadValue(XmlReader reader, ref Answer ans, string answerName, int[] repeatStack)
        {
            if (reader.Name == "RptValue")
            {
                if (!reader.IsEmptyElement)
                {
                    repeatStack = RepeatIndices.Push(repeatStack);
                    reader.Read();                     // read past RptValue element
                    reader.MoveToContent();
                    while (reader.Name != "RptValue" || reader.NodeType != XmlNodeType.EndElement)
                    {
                        ReadValue(reader, ref ans, answerName, repeatStack);
                        RepeatIndices.Increment(repeatStack);
                    }
                    reader.ReadEndElement();
                    reader.MoveToContent();
                }
                else
                {
                    reader.Read();                     // just read past empty element
                    reader.MoveToContent();
                }
            }
            else             // scalar value
            {
                // check for unanswered/user modifiable attributes
                bool unans          = false;
                bool collapsed      = false;
                bool userModifiable = true;
                if (reader.HasAttributes)
                {
                    while (reader.MoveToNextAttribute())
                    {
                        if (reader.Name == "unans")
                        {
                            unans = XmlConvert.ToBoolean(reader.Value);
                        }
                        else if (reader.Name == "userModifiable")
                        {
                            userModifiable = XmlConvert.ToBoolean(reader.Value);
                        }
                    }
                    reader.MoveToElement();
                }
                collapsed = reader.IsEmptyElement;
                // get value
                string s;
                switch (reader.Name)
                {
                case "TextValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <TextValue>(answerName);
                    }
                    s = reader.ReadElementContentAsString(reader.Name, "");
                    if (unans || string.IsNullOrEmpty(s))
                    {
                        ans.InitValue <TextValue>(userModifiable ? TextValue.Unanswered : TextValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        ans.InitValue <TextValue>(new TextValue(s, userModifiable), repeatStack);
                    }
                    break;

                case "NumValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <NumberValue>(answerName);
                    }
                    s = reader.ReadElementContentAsString(reader.Name, "");
                    if (unans || string.IsNullOrEmpty(s))
                    {
                        ans.InitValue <NumberValue>(userModifiable ? NumberValue.Unanswered : NumberValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        ans.InitValue <NumberValue>(new NumberValue(XmlConvert.ToDouble(s), userModifiable), repeatStack);
                    }
                    break;

                case "DateValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <DateValue>(answerName);
                    }
                    s = reader.ReadElementContentAsString(reader.Name, "");
                    if (unans || string.IsNullOrEmpty(s))
                    {
                        ans.InitValue <DateValue>(userModifiable ? DateValue.Unanswered : DateValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        string[] dateParts = s.Split('/', ' ', '-', '.');
                        ans.InitValue <DateValue>(
                            new DateValue(
                                Convert.ToInt32(dateParts[2]),
                                Convert.ToInt32(dateParts[1]),
                                Convert.ToInt32(dateParts[0]),
                                userModifiable
                                ), repeatStack);
                    }
                    break;

                case "TFValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <TrueFalseValue>(answerName);
                    }
                    s = reader.ReadElementContentAsString(reader.Name, "");
                    if (unans || string.IsNullOrEmpty(s))
                    {
                        ans.InitValue <TrueFalseValue>(userModifiable ? TrueFalseValue.Unanswered : TrueFalseValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        // LRS: although the value for a TFValue element should be lower case,
                        // The following line forces the conversion to lower case explicitly
                        // because JavaScript and Silverlight have historically (and incorrectly) set these
                        // values using upper case instead.  (Bug 4429)
                        ans.InitValue <TrueFalseValue>(new TrueFalseValue(XmlConvert.ToBoolean(s.ToLowerInvariant()), userModifiable), repeatStack);
                    }
                    break;

                case "MCValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <MultipleChoiceValue>(answerName);
                    }
                    if (unans || reader.IsEmptyElement)
                    {
                        ans.InitValue <MultipleChoiceValue>(userModifiable ? MultipleChoiceValue.Unanswered : MultipleChoiceValue.UnansweredLocked, repeatStack);
                        reader.ReadInnerXml();     // read past the element and ignore it
                    }
                    else
                    {
                        // the MCValue claims to contain one or more SelValues
                        List <String> mcVals = new List <string>();
                        bool          selValueUnans;                        // The fact that SelValue can have an unans attribute is against the official schema, but
                                                                            // some HotDocs code apparently wasn't aware of that. :-)
                        reader.ReadStartElement("MCValue");
                        reader.MoveToContent();
                        while (reader.Name == "SelValue")
                        {
                            selValueUnans = false;
                            if (reader.HasAttributes)
                            {
                                while (reader.MoveToNextAttribute())
                                {
                                    if (reader.Name == "unans")
                                    {
                                        selValueUnans = XmlConvert.ToBoolean(reader.Value);
                                        break;
                                    }
                                }
                                reader.MoveToElement();
                            }
                            s = reader.ReadElementContentAsString(reader.Name, "");
                            if (!selValueUnans &&
                                (!string.IsNullOrEmpty(s) ||
                                 (s != null && mcVals.Count == 0)            // allow at most a single empty SelValue
                                )
                                )
                            {
                                mcVals.Add(s);
                            }
                            reader.MoveToContent();                            // skip whitespace before next element
                        }
                        if (mcVals.Count == 0)                                 // as good as unanswered
                        {
                            ans.InitValue <MultipleChoiceValue>(userModifiable ? MultipleChoiceValue.Unanswered : MultipleChoiceValue.UnansweredLocked, repeatStack);
                        }
                        else
                        {
                            ans.InitValue <MultipleChoiceValue>(new MultipleChoiceValue(mcVals.ToArray(), userModifiable), repeatStack);
                        }
                        reader.ReadEndElement();     // read past MCValue end element
                    }
                    break;

                default:                         // anything else -- database values, clause library values, document text (span) values
                    if (ans == null)
                    {
                        ans = CreateAnswer <UnknownValue>(answerName);
                    }
                    ans.InitValue <UnknownValue>(new UnknownValue(reader.ReadOuterXml()), repeatStack);
                    break;
                }
                reader.MoveToContent();                 // skip any white space to move to the next element
            }
        }
        private void ReadValue(XmlReader reader, ref Answer ans, string answerName, int[] repeatStack)
        {
            if (reader.Name == "RptValue")
            {
                if (!reader.IsEmptyElement)
                {
                    repeatStack = RepeatIndices.Push(repeatStack);
                    reader.Read();                     // read past RptValue element
                    reader.MoveToContent();
                    while (reader.Name != "RptValue" || reader.NodeType != XmlNodeType.EndElement)
                    {
                        ReadValue(reader, ref ans, answerName, repeatStack);
                        RepeatIndices.Increment(repeatStack);
                    }
                    reader.ReadEndElement();
                    reader.MoveToContent();
                }
                else
                {
                    reader.Read();                     // just read past empty element
                    reader.MoveToContent();
                }
            }
            else             // scalar value
            {
                // check for unanswered/user modifiable attributes
                bool unans          = false;
                bool userModifiable = true;
                if (reader.HasAttributes)
                {
                    while (reader.MoveToNextAttribute())
                    {
                        if (reader.Name == "unans")
                        {
                            unans = XmlConvert.ToBoolean(reader.Value);
                        }
                        else if (reader.Name == "userModifiable")
                        {
                            userModifiable = XmlConvert.ToBoolean(reader.Value);
                        }
                    }
                    reader.MoveToElement();
                }
                // get value
                switch (reader.Name)
                {
                case "TextValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <TextValue>(answerName);
                    }
                    if (unans)
                    {
                        ans.InitValue <TextValue>(userModifiable ? TextValue.Unanswered : TextValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        reader.ReadStartElement("TextValue");
                        ans.InitValue <TextValue>(new TextValue(reader.Value, userModifiable), repeatStack);
                        reader.Read();                         // move past text element
                    }
                    reader.Read();                             // read past TextValue element
                    reader.MoveToContent();
                    break;

                case "NumValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <NumberValue>(answerName);
                    }
                    if (unans)
                    {
                        ans.InitValue <NumberValue>(userModifiable ? NumberValue.Unanswered : NumberValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        reader.ReadStartElement("NumValue");
                        ans.InitValue <NumberValue>(new NumberValue(XmlConvert.ToDouble(reader.Value), userModifiable), repeatStack);
                        reader.Read();                         // move past text element
                    }
                    reader.Read();                             // read past NumValue element
                    reader.MoveToContent();
                    break;

                case "DateValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <DateValue>(answerName);
                    }
                    if (unans)
                    {
                        ans.InitValue <DateValue>(userModifiable ? DateValue.Unanswered : DateValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        reader.ReadStartElement("DateValue");
                        string[] dateParts = reader.Value.Split('/', ' ', '-', '.');
                        ans.InitValue <DateValue>(new DateValue(
                                                      Convert.ToInt32(dateParts[2]), Convert.ToInt32(dateParts[1]), Convert.ToInt32(dateParts[0]), userModifiable
                                                      ), repeatStack);
                        reader.Read();                         // move past text element
                    }
                    reader.Read();                             // read past DateValue element
                    reader.MoveToContent();
                    break;

                case "TFValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <TrueFalseValue>(answerName);
                    }
                    if (unans)
                    {
                        ans.InitValue <TrueFalseValue>(userModifiable ? TrueFalseValue.Unanswered : TrueFalseValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        reader.ReadStartElement("TFValue");
                        // LRS: although the value for a TFValue element should be lower case,
                        // The following line forces the conversion to lower case explicitly
                        // because JavaScript and Silverlight have historically (and incorrectly) set these
                        // values using upper case instead.  (TFS 4429)
                        ans.InitValue <TrueFalseValue>(new TrueFalseValue(XmlConvert.ToBoolean(reader.Value.ToLowerInvariant()), userModifiable), repeatStack);
                        reader.Read();                         // move past text element
                    }
                    reader.Read();                             // read past TFValue element
                    reader.MoveToContent();
                    break;

                case "MCValue":
                    if (ans == null)
                    {
                        ans = CreateAnswer <MultipleChoiceValue>(answerName);
                    }
                    if (unans)
                    {
                        ans.InitValue <MultipleChoiceValue>(userModifiable ? MultipleChoiceValue.Unanswered : MultipleChoiceValue.UnansweredLocked, repeatStack);
                    }
                    else
                    {
                        List <String> mcVals = new List <string>();
                        reader.ReadStartElement("MCValue");
                        reader.MoveToContent();
                        while (reader.Name == "SelValue")
                        {
                            reader.ReadStartElement("SelValue");
                            mcVals.Add(reader.Value);
                            reader.Read();                                     // skip past value
                            reader.ReadEndElement();
                            reader.MoveToContent();
                        }
                        ans.InitValue <MultipleChoiceValue>(new MultipleChoiceValue(mcVals.ToArray(), userModifiable), repeatStack);
                    }
                    reader.Read();                             // read past MCValue element
                    reader.MoveToContent();
                    break;

                default:                         // anything else -- database values, clause library values, document text (span) values
                    if (ans == null)
                    {
                        ans = CreateAnswer <UnknownValue>(answerName);
                    }
                    ans.InitValue <UnknownValue>(new UnknownValue(reader.ReadOuterXml()), repeatStack);
                    break;
                }
                reader.MoveToContent();                 // skip any white space to move to the next element
            }
        }