Ejemplo n.º 1
0
        private SifElement GetContainer(SifElement contentParent, IElementDef childDef, SifVersion version)
        {
            IElementDef elementParentDef = childDef.Parent;

            if (elementParentDef != null && elementParentDef != contentParent.ElementDef)
            {
                // The element does not appear to belong to this parent. Attempt to look
                // for a container element that might be missing in between the two
                // If the parent of this element were collapsed in a previous version
                // of SIF, check for or re-add the parent element and add this new
                // child instead.
                //
                // For example, a child could be an Email element from the
                // common package that's being added to StudentPersonal. In this
                // case,
                // we need to actually find or create an instance of the new
                // EmailList
                // container element and add the child to it, instead of to "this"
                String      tag         = elementParentDef.Tag(Adk.SifVersion);
                IElementDef missingLink = Adk.Dtd.LookupElementDef(contentParent.ElementDef, tag);
                if (missingLink != null && missingLink.IsCollapsed(version))
                {
                    SifElement container = contentParent.GetChild(missingLink);
                    if (container == null)
                    {
                        container = SifElement.Create(contentParent, missingLink);
                    }
                    AddChild(contentParent, container, version);
                    return(container);
                }
            }

            return(contentParent);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Use by SIFXPathContext when determining if it can add a child
        /// or not
        /// </summary>
        /// <param name="childName"></param>
        /// <returns></returns>
        public AddChildDirective GetAddChildDirective(string childName)
        {
            SifElement sifElement = (SifElement)fElement;

            if (sifElement.ChildCount == 0)
            {
                // There are no children. Don't even check for repeatability.
                // This child can be added.
                return(AddChildDirective.ADD);
            }
            IElementDef candidate = GetChildDef(childName);

            if (candidate.Field)
            {
                // Don't evaluate repeatability
                return(AddChildDirective.ADD);
            }

            SifElement instance = sifElement.GetChild(candidate);

            if (instance == null)
            {
                // There are no siblings of this type. This child can be
                // added
                return(AddChildDirective.ADD);
            }
            if (candidate.IsRepeatable(Version))
            {
                // This element is repeatable. This child can be added
                return(AddChildDirective.ADD);
            }

            // A sibling exists, and the element is not repeatable
            return(AddChildDirective.DONT_ADD_NOT_REPEATABLE);
        }
Ejemplo n.º 3
0
        public void EmbeddedSIFMessage()
        {
            SifElement element = null;

            using (Stream aStream = GetResourceStream("GetNextMessageResponse.xml"))
            {
                TextReader aReader = new StreamReader(aStream);
                SifParser  parser  = SifParser.NewInstance();
                element = parser.Parse(aReader, null, SifParserFlags.ExpectInnerEnvelope, SifVersion.SIF11);
                aReader.Close();
                aStream.Close();
            }

            Assert.IsNotNull(element, "SIFElement was not parsed");
            SIF_Ack         ack            = (SIF_Ack)element;
            SifElement      messageElement = ack.SIF_Status.SIF_Data.GetChild("SIF_Message");
            SIF_Event       aEvent         = (SIF_Event)messageElement.GetChild("SIF_Event");
            SIF_EventObject eventObject    = aEvent.SIF_ObjectData.SIF_EventObject;

            Assert.AreEqual("SchoolCourseInfo", eventObject.ObjectName, "Wrong object name");
            Assert.AreEqual("Change", eventObject.Action, "Wrong Action");
            Assert.IsTrue(eventObject.GetChildList()[0] is SchoolCourseInfo, "Wrong object type");
        }
Ejemplo n.º 4
0
        private SifElement GetContainer(SifElement contentParent, IElementDef childDef, SifVersion version)
        {
            IElementDef elementParentDef = childDef.Parent;
            if (elementParentDef != null && elementParentDef != contentParent.ElementDef)
            {
                // The element does not appear to belong to this parent. Attempt to look
                // for a container element that might be missing in between the two
                // If the parent of this element were collapsed in a previous version
                // of SIF, check for or re-add the parent element and add this new
                // child instead.
                //
                // For example, a child could be an Email element from the
                // common package that's being added to StudentPersonal. In this
                // case,
                // we need to actually find or create an instance of the new
                // EmailList
                // container element and add the child to it, instead of to "this"
                String tag = elementParentDef.Tag(Adk.SifVersion);
                IElementDef missingLink = Adk.Dtd.LookupElementDef(contentParent.ElementDef, tag);
                if (missingLink != null && missingLink.IsCollapsed(version))
                {
                    SifElement container = contentParent.GetChild(missingLink);
                    if (container == null)
                    {
                            container = SifElement.Create(contentParent, missingLink);
                    }
                    AddChild(contentParent, container, version);
                    return container;
                }
            }

            return contentParent;
        }
Ejemplo n.º 5
0
        /// <summary>  Recursively parse an XPath-like query.</summary>
        /// <param name="relativeTo">The SifElement this iteration is relative to. For the
        /// first call to this method, the <i>relativeTo</i> parameter is usually
        /// a SifDataObject such as StudentPersonal to which the XPath query
        /// string is relative. With each subsequent call it is the SifElement
        /// or SimpleField that was previously processed.</param>
        /// <param name="curSegment">The current segment of the path that is being processed.
        /// For the first call to this method, the <i>curSegment</i> should be
        /// the portion of the XPath query string up to the first forward slash,
        /// exclusive.</param>
        /// <param name="nextSegment">The remaining portion of the path to be processed.
        /// For the first call to this method, the <i>nextSegment</i> should be
        /// the portion of the XPath query string following the first forward
        /// slash.</param>
        /// <returns> The Element satisfying the query, or <c>null</c> if no
        /// match was found (unless the <i>create</i> parameter is true). If the
        /// query resolves to an attribute, a SimpleField object is returned. If
        /// it resolves to an element, a SifElement object is returned. In both
        /// cases the caller can obtain the text value of the attribute or
        /// element by calling its <c>getTextValue</c> method.
        /// </returns>
        private Element _xpath(SifElement relativeTo, string curSegment, string nextSegment)
        {
            SifElement nextEle = null;

            int attr = curSegment.IndexOf('@');
            int bracket = curSegment.IndexOf('[');
            if (bracket != -1)
            {
                if (attr == -1)
                {
                    throw new AdkSchemaException("Invalid query: \"" + curSegment +
                                                  "\" must be in the form [@Attribute='value']");
                }

                string subEleTag = curSegment.Substring(0, (bracket) - (0));
                SifElement subEle = relativeTo.GetChild(subEleTag);
                if (subEle == null)
                {
                    return null;
                }

                int endBracket = curSegment.IndexOf(']', bracket);
                if (bracket == -1)
                {
                    throw new AdkSchemaException("Invalid query: \"" + curSegment +
                                                  "\" must be in the form [@Attribute='value']");
                }

                List<SearchCond> condsList = new List<SearchCond>(10);
                string conds = curSegment.Substring(bracket + 1, (endBracket) - (bracket + 1));
                string[] tokens = conds.Split(',');
                foreach (string thisTok in tokens)
                {
                    if (thisTok[0] != '@')
                    {
                        throw new AdkSchemaException("Attribute names must be preceded with the @ character: " +
                                                      thisTok);
                    }

                    int eq = thisTok.IndexOf('=');
                    if (eq == -1)
                    {
                        throw new AdkSchemaException("Attribute value must be in the form [@Attribute='value']: " +
                                                      thisTok);
                    }

                    //  Lookup the referenced attribute
                    SimpleField attrEle = subEle.GetField(thisTok.Substring(1, (eq) - (1)));
                    if (attrEle == null)
                    {
                        return null;
                    }

                    //  Add the attribute/value to the list
                    string aval = _attrValue(thisTok.Substring(eq + 1));
                    SearchCond sc = new SearchCond(attrEle.ElementDef, aval);
                    condsList.Add(sc);
                }

                //  Search the parent's subEleTag children for matching attributes.
                //  All attributes in the condsList must match.
                SifElementList ch = relativeTo.GetChildList(subEleTag);
                int chLen = ch.Count;
                for (int i = 0; i < chLen && nextEle == null; i++)
                {
                    SifElement cmpEle;
                    cmpEle = ch[i];

                    int matched = 0;

                    //  Compare the attributes
                    for (int x = 0; x < condsList.Count; x++)
                    {
                        SearchCond sc = condsList[x];
                        SimpleField atr = cmpEle.GetField(sc.fAttr);
                        if (atr == null)
                        {
                            break;
                        }
                        if (atr.TextValue.Equals(sc.fValue))
                        {
                            matched++;
                        }
                    }

                    //  If all attributes matched, this is a match
                    if (matched == condsList.Count)
                    {
                        nextEle = cmpEle;

                        //  Continue the search if nextSegment has a value
                        if (nextSegment != null && nextSegment.Length > 0)
                        {
                            int ii = nextSegment.IndexOf('/');

                            Element ee =
                                _xpath(nextEle, ii == -1 ? nextSegment : nextSegment.Substring(0, (ii) - (0)),
                                        ii == -1 ? null : nextSegment.Substring(ii + 1));
                            if (ee != null)
                            {
                                return ee;
                            }
                            else
                            {
                                nextEle = null;
                            }
                        }
                    }
                }

                if (nextEle == null)
                {
                    return null;
                }
            }
            else
            {
                //  Search for the named attribute/element
                if (attr != -1)
                {
                    return relativeTo.GetField(curSegment.Substring(1));
                }
                else
                {
                    nextEle = relativeTo.GetChild(curSegment);
                    if (nextEle == null)
                    {
                        if (nextSegment == null || (nextSegment.Length > 0 && nextSegment[0] == '@'))
                        {
                            return relativeTo.GetField(curSegment);
                        }

                        return null;
                    }
                }
            }

            //  Continue the search if nextSegment has a value
            if ((nextSegment != null && nextSegment.Length > 0))
            {
                int i = nextSegment.IndexOf('/');

                return
                    _xpath(nextEle, i == -1 ? nextSegment : nextSegment.Substring(0, (i) - (0)),
                            i == -1 ? null : nextSegment.Substring(i + 1));
            }

            return nextEle;
        }
Ejemplo n.º 6
0
        /// <summary>  Recursively builds elements and attributes relative to a SifElement.</summary>
        /// <param name="relativeTo">The SifElement this iteration is relative to. For the
        /// first call to this method, the <i>relativeTo</i> parameter is usually
        /// a SifDataObject such as StudentPersonal to which the XPath query
        /// string is relative. With each subsequent call it is the SifElement
        /// or SimpleField that was previously processed.</param>
        /// <param name="path">A running path of the segments processed thus far; an empty
        /// StringBuffer should be passed to this parameter the first time the
        /// method is called </param>
        /// <param name="curSegment">The current segment of the path that is being processed.
        /// For the first call to this method, the <i>curSegment</i> should be
        /// the portion of the XPath query string up to the first forward slash,
        /// exclusive.</param>
        /// <param name="nextSegment">The remaining portion of the path to be processed.
        /// For the first call to this method, the <i>nextSegment</i> should be
        /// the portion of the XPath query string following the first forward
        /// slash.</param>
        /// <param name="prevAttributes">An optional array of attribute values that were
        /// used to construct an Element in the processing of the last segment.
        /// The array is comprised of attribute name and value pairs such that
        /// element N is an attribute name and N+1 is its value. For the first
        /// call to this method, the array should be null. For subsequent calls,
        /// it should be null unless an Element was constructed from attribute
        /// values.</param>
        /// <param name="version">The version of SIF for which this mapping operation is being evaluated</param>
        /// <param name="textFormatter">The SIFFormatter instance used to parse strings into strongly-typed data values.
        /// For many uses of this API, this formatter is equivalent to ADK.TextFormatter</param>
        /// <param name="pathFormatter">The SIFFormatter instance used for setting child SIFElements on their parents.
        /// This formatter may be different than the text formatter. The text formatter is, for
        /// compatibility's sake defaulted to SIF 1.x. However, the path formatter must be 
        /// correct for the mappings path being evaluated.</param>
        /// <param name="valueBuilder"></param>
        /// <returns> The Element satisfying the query, or <c>null</c> if no
        /// match was found (unless the <i>create</i> parameter is true). If the
        /// query resolves to an attribute, a SimpleField object is returned. If
        /// it resolves to an element, a SifElement object is returned. In both
        /// cases the caller can obtain the text value of the attribute or
        /// element by calling its <c>TextValue</c> Property.
        /// </returns>
        private Element _xpathBuild(
            SifElement relativeTo,
            StringBuilder path,
            string curSegment,
            string nextSegment,
            string[] prevAttributes,
            IValueBuilder valueBuilder,
            SifVersion version,
            SifFormatter textFormatter,
            SifFormatter pathFormatter)
        {
            string[] _prevAttributes = null;
            SifElement nextEle = null;

            int asgnEq = curSegment.LastIndexOf('=');
            int attr = curSegment.LastIndexOf('@', asgnEq == -1 ? curSegment.Length - 1 : asgnEq - 1);
            int bracket = curSegment.IndexOf('[');
            if (bracket != -1)
            {
                if (attr == -1)
                {
                    throw new AdkSchemaException("Invalid query: \"" + curSegment +
                                                  "\" must be in the form [@Attr='value1','value2',...]");
                }

                string subEleTag = curSegment.Substring(0, (bracket) - (0));

                int lastBracket = curSegment.LastIndexOf(']');
                string[] attrList = curSegment.Substring(bracket + 1, (lastBracket) - (bracket + 1)).Split(',');
                _prevAttributes = new string[attrList.Length * 2];
                int _prevI = 0;

                for (int a = 0; a < attrList.Length; a++)
                {
                    string _curSegment = attrList[a];

                    //  Determine the value of the attribute
                    int eq = _curSegment.IndexOf("=");
                    string val = _curSegment.Substring(eq + 1);
                    string v = null;
                    if (val[0] == '\'')
                    {
                        int end = val.IndexOf('\'', 1);
                        if (end != -1)
                        {
                            v = valueBuilder == null
                                    ? val.Substring(1, (end) - (1))
                                    : valueBuilder.Evaluate(val.Substring(1, (end) - (1)));
                        }
                    }

                    if (v == null)
                    {
                        throw new AdkSchemaException("Attribute value (" + val +
                                                      ") must be in the form @Attribute='value'");
                    }

                    string attrName = _curSegment.Substring(1, (eq) - (1));

                    _prevAttributes[_prevI++] = attrName;
                    _prevAttributes[_prevI++] = v;

                    if (nextEle == null)
                    {
                        //
                        //  Look at all of the peer elements to determine if any have the
                        //  attribute value set. If so, return it; otherwise create a new
                        //  instance of the element with the attribute set. For example, if
                        //  curSegment is "Address[@Type='M']", we must look at all of the
                        //  Address children of relativeTo in order to determine if any
                        //  currently exist with a Type field set to a value of 'M'. If one
                        //  does, then it already exists and there is nothing to do; if
                        //  not found, however, a new Address child must be added with a
                        //  Type field of 'M'.
                        //

                        //  Lookup the IElementDef of relativeTo
                        IElementDef subEleDef = Adk.Dtd.LookupElementDef(relativeTo.ElementDef, subEleTag);
                        if (subEleDef == null)
                        {
                            subEleDef = Adk.Dtd.LookupElementDef(subEleTag);
                            if (subEleDef == null)
                            {
                                throw new AdkSchemaException(subEleTag + " is not a recognized attribute of " +
                                                              relativeTo.Tag);
                            }
                        }

                        bool repeatable = subEleDef.IsRepeatable(relativeTo.SifVersion);

                        SifElementList peers = relativeTo.GetChildList(subEleDef);

                        if (curSegment.IndexOf("+]") == -1)
                        {
                            //
                            //  Determine if relatSifElementListiveTo has any children that already
                            //  define this attribute/value; if not, create a new instance.
                            //  If subEleDef is not repeatable, however, we cannot add
                            //  another instance of it regardless.
                            //
                            for (int i = 0; i < peers.Count && nextEle == null; i++)
                            {
                                SimpleField ftest = peers[i].GetField(attrName);
                                if (ftest != null && ftest.TextValue.Equals(v))
                                {
                                    nextEle = peers[i];
                                }
                            }
                        }

                        if (nextEle == null)
                        {
                            if (!(peers.Count > 0 && !repeatable))
                            {
                                nextEle =
                                    _createChild(relativeTo, subEleTag, valueBuilder, version, textFormatter,
                                                  pathFormatter);
                            }
                            else
                            {
                                //
                                //  subEleDef is not repeatable, so we need to back up
                                //  and add this attribute/value to a fresh instance of
                                //  relativeTo if possible. First use _xpath(path) to try
                                //  to select that instance in case it already exists (otherwise
                                //  we'd create a new instance each iteration, which is
                                //  not the desired result.)
                                //

                                string _tmp;
                                if (path.Length > 0)
                                {
                                    _tmp = path + "/" + curSegment;
                                }
                                else
                                {
                                    _tmp = curSegment;
                                }
                                if (XPATH_DEBUG)
                                {
                                    Console.Out.Write("Searching for path relative to " +
                                                       relativeTo.Root.ElementDef.Name + ": " + _tmp);
                                }

                                int _del = _tmp.IndexOf('/');
                                nextEle =
                                    (SifElement)
                                    _xpath((SifElement)relativeTo.Root,
                                            _tmp.Substring(0, (_del == -1 ? _tmp.Length : _del) - (0)),
                                            _del == -1 ? null : _tmp.Substring(_del + 1));

                                if (XPATH_DEBUG)
                                {
                                    if (nextEle == null)
                                    {
                                        Console.Out.WriteLine("; not found, a new instance will be created");
                                    }
                                    else
                                    {
                                        Console.Out.WriteLine("; found");
                                    }
                                }

                                if (nextEle == null)
                                {
                                    if (relativeTo.ElementDef.IsRepeatable(relativeTo.SifVersion))
                                    {
                                        //  Clone relativeTo
                                        SifElement grandParent = (SifElement)relativeTo.Parent;
                                        nextEle = SifElement.Create(grandParent, relativeTo.ElementDef);
                                        pathFormatter.AddChild(grandParent, nextEle, version);

                                        //  Clone subEleDef; this now becomes nextEle
                                        SifElement newEle = SifElement.Create(nextEle, subEleDef);
                                        pathFormatter.AddChild(nextEle, newEle, version);
                                        _copyAttributes(nextEle, prevAttributes);
                                        nextEle = newEle;
                                    }
                                    else
                                    {
                                        throw new AdkSchemaException(
                                            "It is not possible to create the element or attribute identified by this path: " +
                                            _tmp + (nextSegment == null ? "" : "/" + nextSegment) +
                                            ". The element or attribute is either undefined in this version of SIF, " +
                                            "or an attempt is being made to create another instance of an element that is not Repeatable.");
                                    }
                                }
                            }
                        }
                    }

                    if (nextEle != null)
                    {
                        _createField(nextEle, attrName, v);
                    }

                    if (a == attrList.Length && nextEle == null)
                    {
                        return null;
                    }
                }
            }
            else
            {
                //  Search for the named attribute/element
                if (attr != -1)
                {
                    SimpleField ff = relativeTo.GetField(curSegment.Substring(1));
                    if (ff == null)
                    {
                        ff = _createField(relativeTo, curSegment.Substring(1), null);
                    }

                    return ff;
                }
                else
                {
                    string _tag = curSegment;
                    int eq = curSegment.IndexOf('=');
                    if (eq != -1)
                    {
                        _tag = curSegment.Substring(0, (eq) - (0));
                    }

                    nextEle = relativeTo.GetChild(_tag);
                    if (nextEle == null)
                    {
                        //  The curSegment element does not exist as a child of the relativeTo
                        //  object, so create it.
                        nextEle =
                            _createChild(relativeTo, curSegment, valueBuilder, version, textFormatter, pathFormatter);
                        if (nextEle == null)
                        {
                            if (nextSegment == null)
                            {
                                return relativeTo.GetField(_tag);
                            }
                            return null;
                        }
                    }
                }
            }

            //  Continue the search if nextSegment has a value
            if (nextEle != null && (nextSegment != null && nextSegment.Length > 0))
            {
                int i = nextSegment.IndexOf('/');

                if (path.Length > 0)
                {
                    path.Append("/");
                }
                path.Append(curSegment);

                return _xpathBuild(
                    nextEle,
                    path, i == -1 ? nextSegment : nextSegment.Substring(0, (i)),
                    i == -1 ? null : nextSegment.Substring(i + 1),
                    _prevAttributes,
                    valueBuilder,
                    version,
                    textFormatter,
                    pathFormatter);
            }

            if (nextSegment == null && nextEle != null && (nextEle.TextValue == null || nextEle.TextValue.Length == 0))
            {
                int eq2 = curSegment.LastIndexOf('=');
                if (eq2 != -1)
                {
                    if (bracket == -1 || (curSegment.LastIndexOf(']') < eq2))
                    {
                        //
                        //  An equals sign in the final segment indicates there is
                        //  a value constant or expression following the XPath
                        //  (e.g. "OtherId[@Type='06']=@pad($(PERMNUM),0,5)" ). Use
                        //  the user-supplied ValueBuilder to evaluate it.
                        //
                        string str = curSegment.Substring(eq2 + 1);
                        nextEle.TextValue = valueBuilder == null ? str : valueBuilder.Evaluate(str);
                    }
                }
            }

            return nextEle;
        }