//*************************************************************************
        //  Method: AppendFromUserXmlNode()
        //
        /// <summary>
        /// Appends GraphML-Attribute values from a "user" XML node returned by
        /// Twitter to a vertex XML node.
        /// </summary>
        ///
        /// <param name="oUserXmlNode">
        /// The "user" XML node returned by Twitter.  Can't be null.
        /// </param>
        /// 
        /// <param name="oGraphMLXmlDocument">
        /// GraphMLXmlDocument being populated.
        /// </param>
        ///
        /// <param name="oTwitterVertex">
        /// Contains the vertex XML node from <paramref
        /// name="oGraphMLXmlDocument" /> to add the GraphML attribute values to.
        /// </param>
        ///
        /// <param name="bIncludeStatistics">
        /// true to include the user's statistics.
        /// </param>
        ///
        /// <param name="bIncludeLatestStatus">
        /// true to include a latest status attribute value.
        /// </param>
        ///
        /// <remarks>
        /// This method reads information from a "user" XML node returned by
        /// Twitter and appends the information to a vertex XML node in the GraphML
        /// document.
        /// </remarks>
        //*************************************************************************
        protected void AppendFromUserXmlNode(
            XmlNode oUserXmlNode,
            GraphMLXmlDocument oGraphMLXmlDocument,
            TwitterVertex oTwitterVertex,
            Boolean bIncludeStatistics,
            Boolean bIncludeLatestStatus
            )
        {
            Debug.Assert(oUserXmlNode != null);
            Debug.Assert(oGraphMLXmlDocument != null);
            Debug.Assert(oTwitterVertex != null);
            AssertValid();

            XmlNode oVertexXmlNode = oTwitterVertex.VertexXmlNode;

            if (bIncludeStatistics)
            {
            AppendInt32GraphMLAttributeValue(oUserXmlNode,
                "friends_count/text()", null, oGraphMLXmlDocument,
                oVertexXmlNode, FollowedID);

            AppendInt32GraphMLAttributeValue(oUserXmlNode,
                "followers_count/text()", null, oGraphMLXmlDocument,
                oVertexXmlNode, FollowersID);

            AppendInt32GraphMLAttributeValue(oUserXmlNode,
                "statuses_count/text()", null, oGraphMLXmlDocument,
                oVertexXmlNode, StatusesID);

            AppendInt32GraphMLAttributeValue(oUserXmlNode,
                "favourites_count/text()", null, oGraphMLXmlDocument,
                oVertexXmlNode, FavoritesID);

            AppendStringGraphMLAttributeValue(oUserXmlNode,
                "description/text()", null, oGraphMLXmlDocument,
                oVertexXmlNode, DescriptionID);

            AppendStringGraphMLAttributeValue(oUserXmlNode,
                "time_zone/text()", null, oGraphMLXmlDocument, oVertexXmlNode,
                TimeZoneID);

            AppendStringGraphMLAttributeValue(oUserXmlNode,
                "utc_offset/text()", null, oGraphMLXmlDocument, oVertexXmlNode,
                UtcOffsetID);

            String sJoinedDateUtc;

            if ( XmlUtil2.TrySelectSingleNodeAsString(oUserXmlNode,
                "created_at/text()", null, out sJoinedDateUtc) )
            {
                oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                    oVertexXmlNode, JoinedDateUtcID,
                    TwitterDateParser.ParseTwitterDate(sJoinedDateUtc) );
            }
            }

            String sLatestStatus;

            if ( XmlUtil2.TrySelectSingleNodeAsString(oUserXmlNode,
            "status/text/text()", null, out sLatestStatus) )
            {
            String sLatestStatusDateUtc;

            if ( XmlUtil2.TrySelectSingleNodeAsString(oUserXmlNode,
                "status/created_at/text()", null, out sLatestStatusDateUtc) )
            {
                sLatestStatusDateUtc = TwitterDateParser.ParseTwitterDate(
                    sLatestStatusDateUtc);
            }

            // Don't overwrite any status the derived class may have already
            // stored on the TwitterVertex object.

            if (oTwitterVertex.StatusForAnalysis == null)
            {
                oTwitterVertex.StatusForAnalysis = sLatestStatus;
                oTwitterVertex.StatusForAnalysisDateUtc = sLatestStatusDateUtc;
            }

            if (bIncludeLatestStatus)
            {
                oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode,
                    LatestStatusID, sLatestStatus);

                if ( !String.IsNullOrEmpty(sLatestStatusDateUtc) )
                {
                    oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                        oVertexXmlNode, LatestStatusDateUtcID,
                        sLatestStatusDateUtc);
                }
            }
            }

            // Add an image URL GraphML-attribute if it hasn't already been added.
            // (It might have been added from an "entry" node by
            // TwitterSearchNetworkAnalyzer.)

            if (oVertexXmlNode.SelectSingleNode(
            "a:data[@key='" + ImageFileID + "']",
            oGraphMLXmlDocument.CreateXmlNamespaceManager("a") ) == null)
            {
            AppendStringGraphMLAttributeValue(oUserXmlNode,
                "profile_image_url/text()", null, oGraphMLXmlDocument,
                oVertexXmlNode, ImageFileID);
            }
        }
        //*************************************************************************
        //  Method: TryAppendVertexXmlNode()
        //
        /// <overloads>
        /// Appends a vertex XML node to the GraphML document for a person if such
        /// a node doesn't already exist.
        /// </overloads>
        ///
        /// <summary>
        /// Appends a vertex XML node to the GraphML document for a person if such
        /// a node doesn't already exist and provides the TwitterVertex for the
        /// node.
        /// </summary>
        ///
        /// <param name="sScreenName">
        /// Screen name to add a vertex XML node for.
        /// </param>
        ///
        /// <param name="oUserXmlNode">
        /// The "user" XML node returned by Twitter, or null if a user node isn't
        /// available.
        /// </param>
        ///
        /// <param name="oGraphMLXmlDocument">
        /// GraphMLXmlDocument being populated.
        /// </param>
        ///
        /// <param name="oScreenNameDictionary">
        /// The key is the screen name in lower case and the value is the
        /// corresponding TwitterVertex.
        /// </param>
        ///
        /// <param name="bIncludeStatistics">
        /// true to include the user's statistics if <paramref
        /// name="oUserXmlNode" /> is not null.
        /// </param>
        ///
        /// <param name="bIncludeLatestStatus">
        /// true to include a latest status attribute value if <paramref
        /// name="oUserXmlNode" /> is not null.
        /// </param>
        ///
        /// <param name="oTwitterVertex">
        /// Where the TwitterVertex that wraps the vertex XML node gets stored.
        /// This gets set regardless of whether the node already existed.
        /// </param>
        ///
        /// <returns>
        /// true if a vertex XML node was added, false if a vertex XML node already
        /// existed.
        /// </returns>
        //*************************************************************************
        protected Boolean TryAppendVertexXmlNode(
            String sScreenName,
            XmlNode oUserXmlNode,
            GraphMLXmlDocument oGraphMLXmlDocument,
            Dictionary<String, TwitterVertex> oScreenNameDictionary,
            Boolean bIncludeStatistics,
            Boolean bIncludeLatestStatus,
            out TwitterVertex oTwitterVertex
            )
        {
            Debug.Assert( !String.IsNullOrEmpty(sScreenName) );
            Debug.Assert(oGraphMLXmlDocument != null);
            Debug.Assert(oScreenNameDictionary != null);

            oTwitterVertex = null;

            if ( oScreenNameDictionary.TryGetValue(sScreenName,
            out oTwitterVertex) )
            {
            return (false);
            }

            XmlNode oVertexXmlNode = oGraphMLXmlDocument.AppendVertexXmlNode(
            sScreenName);

            oTwitterVertex = new TwitterVertex(oVertexXmlNode);
            oScreenNameDictionary.Add(sScreenName, oTwitterVertex);

            oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode,
            MenuTextID, "Open Twitter Page for This Person");

            oGraphMLXmlDocument.AppendGraphMLAttributeValue( oVertexXmlNode,
            MenuActionID, String.Format(WebPageUrlPattern, sScreenName) );

            if (oUserXmlNode != null)
            {
            AppendFromUserXmlNode(oUserXmlNode, oGraphMLXmlDocument,
                oTwitterVertex, bIncludeStatistics, bIncludeLatestStatus);
            }

            return (true);
        }