public bool ReadRaw(XmlReader reader,
                            SifVersion version,
                            SifElement parent,
                            SifFormatter formatter)
        {
            string name = reader.LocalName;

            if (name.Equals(fDateElement))
            {
                String   dateValue = ConsumeElementTextValue(reader, version);
                DateTime?date      = formatter.ToDate(dateValue);
                if (date.HasValue)
                {
                    DateTime    tsValue  = date.Value;
                    SifDateTime dateTime = new SifDateTime(tsValue);
                    parent.SetField(dateTime.CreateField(parent, fElementDef));
                }
            }
            else if (name.Equals(fTimeElement))
            {
                String   timeValue = ConsumeElementTextValue(reader, version);
                DateTime?time      = formatter.ToTime(timeValue);
                if (time.HasValue)
                {
                    DateTime val = time.Value;
                    // See if the Timestamp field already exists on the parent
                    SimpleField timeStampField = parent.GetField(fElementDef);
                    if (timeStampField == null)
                    {
                        // Doesn't exist, create it
                        SifDateTime dateTime = new SifDateTime(val);
                        parent.SetField(dateTime.CreateField(parent, fElementDef));
                    }
                    else
                    {
                        // Exists, update the time portion of the date
                        SifDateTime sdt = (SifDateTime)timeStampField.SifValue;
                        if (sdt != null && sdt.Value.HasValue)
                        {
                            DateTime tsValue = sdt.Value.Value;
                            tsValue = tsValue.Add(val.TimeOfDay);
                            sdt     = new SifDateTime(tsValue);
                            // Overwrite the current value
                            parent.SetField(sdt.CreateField(parent, fElementDef));
                        }
                    }
                }
            }
            else
            {
                return(false);
            }

            return(true);
        }
Exemple #2
0
        private void Write(SifElement o, int mode, Boolean isLegacy)
        {
            if (!Include(o))
            {
                return;
            }


            //  "<tag [attr...]>[text]" or "<tag [attr...]/>"
            string tag = o.ElementDef.Tag(fVersion);

            fWriter.WriteStartElement(tag);
            if (!fRootAttributesWritten)
            {
                writeRootAttributes(false);
            }
            WriteAttributes(o);
            if (mode == EMPTY)
            {
                fWriter.WriteEndElement();
            }
            else
            {
                // Check for a text value (or an xs:nil value)
                SimpleField elementValue = o.GetField(o.ElementDef);
                if (elementValue != null)
                {
                    SifSimpleType sst = elementValue.SifValue;
                    if (sst == null || sst.RawValue == null)
                    {
                        // The value of this element has been set and it is
                        // null. This should be rendered as 'xs:nil' in SIF 2.x and greater
                        if (!isLegacy)
                        {
                            fWriter.WriteAttributeString(NIL, XmlSchema.InstanceNamespace, "true");
                        }
                    }
                    else
                    {
                        if (o.DoNotEncode)
                        {
                            fWriter.WriteRaw(o.TextValue);
                        }
                        else
                        {
                            String xmlValue = sst.ToString(fFormatter);
                            fWriter.WriteString(xmlValue);
                        }
                    }
                }
            }
        }
        public bool ReadRaw( XmlReader reader,
                             SifVersion version,
                             SifElement parent,
                             SifFormatter formatter )
        {
            string name = reader.LocalName;

            if ( name.Equals( fDateElement ) )
            {
                String dateValue = ConsumeElementTextValue( reader, version );
                DateTime? date = formatter.ToDate( dateValue );
                if ( date.HasValue )
                {
                    DateTime tsValue = date.Value;
                    SifDateTime dateTime = new SifDateTime( tsValue );
                    parent.SetField( dateTime.CreateField( parent, fElementDef ) );
                }
            }
            else if ( name.Equals( fTimeElement ) )
            {
                String timeValue = ConsumeElementTextValue( reader, version );
                DateTime? time = formatter.ToTime( timeValue );
                if ( time.HasValue )
                {
                    DateTime val = time.Value;
                    // See if the Timestamp field already exists on the parent
                    SimpleField timeStampField = parent.GetField( fElementDef );
                    if ( timeStampField == null )
                    {
                        // Doesn't exist, create it
                        SifDateTime dateTime = new SifDateTime( val );
                        parent.SetField( dateTime.CreateField( parent, fElementDef ) );
                    }
                    else
                    {
                        // Exists, update the time portion of the date
                        SifDateTime sdt = (SifDateTime) timeStampField.SifValue;
                        if ( sdt != null && sdt.Value.HasValue )
                        {
                            DateTime tsValue = sdt.Value.Value;
                            tsValue = tsValue.Add( val.TimeOfDay );
                            sdt = new SifDateTime( tsValue );
                            // Overwrite the current value
                            parent.SetField( sdt.CreateField( parent, fElementDef ) );
                        }
                    }
                }
            }
            else
            {
                return false;
            }

            return true;
        }
Exemple #4
0
        private void Write( SifElement o, int mode, Boolean isLegacy )
        {
            if ( !Include( o ) )
            {
                return;
            }

            //  "<tag [attr...]>[text]" or "<tag [attr...]/>"
            string tag = o.ElementDef.Tag( fVersion );
            fWriter.WriteStartElement( tag );
            if (!fRootAttributesWritten)
            {
                writeRootAttributes(false);
            }
            WriteAttributes( o );
            if ( mode == EMPTY )
            {
                fWriter.WriteEndElement();
            }
            else
            {
                // Check for a text value (or an xs:nil value)
                SimpleField elementValue = o.GetField( o.ElementDef );
                if ( elementValue != null )
                {
                    SifSimpleType sst = elementValue.SifValue;
                    if ( sst == null || sst.RawValue == null )
                    {
                        // The value of this element has been set and it is
                        // null. This should be rendered as 'xs:nil' in SIF 2.x and greater
                        if ( !isLegacy )
                        {
                            fWriter.WriteAttributeString(NIL, XmlSchema.InstanceNamespace, "true");
                        }
                    }
                    else
                    {
                        if ( o.DoNotEncode )
                        {
                            fWriter.WriteRaw( o.TextValue );
                        }
                        else
                        {
                            String xmlValue = sst.ToString( fFormatter );
                            fWriter.WriteString( xmlValue );
                        }
                    }
                }
            }
        }
        /// <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;
        }
        /// <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;
        }