Represents a user in a Twitter network.
This class wraps the GraphML XML node that represents a user in a Twitter network, together with one or more statuses for the user.

This is meant for use while creating Twitter GraphML XML documents for use with the NodeXL Excel Template.

Inheritance: Object
    AppendLatestStatusInformationFromValueDictionary
    (
        Dictionary<String, Object> oStatusValueDictionary,
        GraphMLXmlDocument oGraphMLXmlDocument,
        TwitterUser oTwitterUser,
        Boolean bIncludeLatestStatus,
        Boolean bExpandLatestStatusUrls
    )
    {
        Debug.Assert(oStatusValueDictionary != null);
        Debug.Assert(oGraphMLXmlDocument != null);
        Debug.Assert(oTwitterUser != null);
        AssertValid();

        TwitterStatus oTwitterStatus;

        if ( !TwitterStatus.TryFromStatusValueDictionary(
            oStatusValueDictionary, bExpandLatestStatusUrls,
            out oTwitterStatus) )
        {
            return;
        }

        XmlNode oVertexXmlNode = oTwitterUser.VertexXmlNode;

        if (bIncludeLatestStatus)
        {
            // Add the status to the vertex XML node.

            oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                oVertexXmlNode, TwitterGraphMLUtil.VertexLatestStatusID,
                oTwitterStatus.Text);

            String sLatestStatusUrls = oTwitterStatus.Urls;

            if ( !String.IsNullOrEmpty(sLatestStatusUrls) )
            {
                oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                    oVertexXmlNode,
                    TwitterGraphMLUtil.VertexLatestStatusUrlsID,
                    sLatestStatusUrls);

                oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                    oVertexXmlNode,
                    TwitterGraphMLUtil.VertexLatestStatusDomainsID,
                    TwitterGraphMLUtil.UrlsToDomains(sLatestStatusUrls) ); 
            }

            String sLatestStatusHashtags = oTwitterStatus.Hashtags;

            if ( !String.IsNullOrEmpty(sLatestStatusHashtags) )
            {
                oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                    oVertexXmlNode,
                    TwitterGraphMLUtil.VertexLatestStatusHashtagsID,
                    sLatestStatusHashtags);
            }

            if ( !String.IsNullOrEmpty(oTwitterStatus.ParsedDateUtc) )
            {
                oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                    oVertexXmlNode,
                    TwitterGraphMLUtil.VertexLatestStatusDateUtcID,
                    oTwitterStatus.ParsedDateUtc);
            }

            TwitterGraphMLUtil.
                AppendLatitudeAndLongitudeGraphMLAttributeValues(
                    oGraphMLXmlDocument, oVertexXmlNode,
                    oTwitterStatus.Latitude, oTwitterStatus.Longitude);

            TwitterGraphMLUtil.AppendInReplyToStatusIDGraphMLAttributeValue(
                oGraphMLXmlDocument, oVertexXmlNode,
                oTwitterStatus.InReplyToStatusID);
        }

        oTwitterUser.Statuses.Add(oTwitterStatus);
    }
    AppendUserStatisticsFromValueDictionary
    (
        Dictionary<String, Object> userValueDictionary,
        GraphMLXmlDocument graphMLXmlDocument,
        TwitterUser twitterUser
    )
    {
        Debug.Assert(userValueDictionary != null);
        Debug.Assert(graphMLXmlDocument != null);
        Debug.Assert(twitterUser != null);

        XmlNode vertexXmlNode = twitterUser.VertexXmlNode;

        AppendValueFromValueDictionary(userValueDictionary,
            "friends_count", graphMLXmlDocument, vertexXmlNode,
            VertexFollowedID);

        AppendValueFromValueDictionary(userValueDictionary,
            "followers_count", graphMLXmlDocument, vertexXmlNode,
            VertexFollowersID);

        AppendValueFromValueDictionary(userValueDictionary,
            "statuses_count", graphMLXmlDocument, vertexXmlNode,
            VertexStatusesID);

        AppendValueFromValueDictionary(userValueDictionary,
            "favourites_count", graphMLXmlDocument, vertexXmlNode,
            VertexFavoritesID);

        AppendValueFromValueDictionary(userValueDictionary,
            "description", graphMLXmlDocument, vertexXmlNode,
            VertexDescriptionID);

        AppendValueFromValueDictionary(userValueDictionary,
            "location", graphMLXmlDocument, vertexXmlNode,
            VertexLocationID);

        AppendValueFromValueDictionary(userValueDictionary,
            "url", graphMLXmlDocument, vertexXmlNode,
            VertexUrlID);

        AppendValueFromValueDictionary(userValueDictionary,
            "time_zone", graphMLXmlDocument, vertexXmlNode,
            VertexTimeZoneID);

        AppendValueFromValueDictionary(userValueDictionary,
            "utc_offset", graphMLXmlDocument, vertexXmlNode,
            VertexUtcOffsetID);

        String joinedDateUtc;

        if ( TwitterJsonUtil.TryGetJsonValueFromDictionary(userValueDictionary,
            "created_at", out joinedDateUtc) )
        {
            graphMLXmlDocument.AppendGraphMLAttributeValue(
                vertexXmlNode, VertexJoinedDateUtcID,
                TwitterDateParser.ParseTwitterDate(joinedDateUtc) );
        }
    }
    AppendUserInformationFromValueDictionary
    (
        Dictionary<String, Object> oUserValueDictionary,
        GraphMLXmlDocument oGraphMLXmlDocument,
        TwitterUser oTwitterUser,
        Boolean bIncludeStatistics,
        Boolean bIncludeLatestStatus,
        Boolean bExpandLatestStatusUrls
    )
    {
        Debug.Assert(oUserValueDictionary != null);
        Debug.Assert(oGraphMLXmlDocument != null);
        Debug.Assert(oTwitterUser != null);
        AssertValid();

        TwitterGraphMLUtil.AppendCommonUserInformationFromValueDictionary(
            oUserValueDictionary, oGraphMLXmlDocument, oTwitterUser);

        if (bIncludeStatistics)
        {
            TwitterGraphMLUtil.AppendUserStatisticsFromValueDictionary(
                oUserValueDictionary, oGraphMLXmlDocument, oTwitterUser);
        }

        // Process the user's latest status if requested.

        Object oStatusValueDictionaryAsObject;

        if (
            bIncludeLatestStatus
            &&
            oUserValueDictionary.TryGetValue("status",
                out oStatusValueDictionaryAsObject)
            &&
            oStatusValueDictionaryAsObject is Dictionary<String, Object>
            )
        {
            Dictionary<String, Object> oStatusValueDictionary =
                ( Dictionary<String, Object> )oStatusValueDictionaryAsObject;

            AppendLatestStatusInformationFromValueDictionary(
                oStatusValueDictionary, oGraphMLXmlDocument, oTwitterUser,
                bIncludeLatestStatus, bExpandLatestStatusUrls);
        }
    }
    AppendCommonUserInformationFromValueDictionary
    (
        Dictionary<String, Object> userValueDictionary,
        GraphMLXmlDocument graphMLXmlDocument,
        TwitterUser twitterUser
    )
    {
        Debug.Assert(userValueDictionary != null);
        Debug.Assert(graphMLXmlDocument != null);
        Debug.Assert(twitterUser != null);

        XmlNode vertexXmlNode = twitterUser.VertexXmlNode;

        // Always include an image file.

        AppendValueFromValueDictionary(userValueDictionary,
            "profile_image_url", graphMLXmlDocument, vertexXmlNode,
            NodeXLGraphMLUtil.VertexImageFileID);
    }
    TryAppendVertexXmlNode
    (
        String screenName,
        String userID,
        GraphMLXmlDocument graphMLXmlDocument,
        Dictionary<String, TwitterUser> userIDDictionary,
        out TwitterUser twitterUser
    )
    {
        Debug.Assert( !String.IsNullOrEmpty(screenName) );
        Debug.Assert( !String.IsNullOrEmpty(userID) );
        Debug.Assert(graphMLXmlDocument != null);
        Debug.Assert(userIDDictionary != null);

        twitterUser = null;

        if ( userIDDictionary.TryGetValue(userID, out twitterUser) )
        {
            // A vertex XML node already exists.

            return (false);
        }

        XmlNode vertexXmlNode = graphMLXmlDocument.AppendVertexXmlNode(
            screenName);

        twitterUser = new TwitterUser(screenName, vertexXmlNode);
        userIDDictionary.Add(userID, twitterUser);

        graphMLXmlDocument.AppendGraphMLAttributeValue(vertexXmlNode,
            NodeXLGraphMLUtil.VertexMenuTextID,
            "Open Twitter Page for This Person");

        graphMLXmlDocument.AppendGraphMLAttributeValue(
            vertexXmlNode,
            NodeXLGraphMLUtil.VertexMenuActionID,
            String.Format(TwitterApiUrls.UserWebPageUrlPattern, screenName)
            );

        return (true);
    }
    AppendTweetedSearchTermGraphMLAttributeValue
    (
        GraphMLXmlDocument graphMLXmlDocument,
        TwitterUser twitterUser,
        Boolean userTweetedSearchTerm
    )
    {
        Debug.Assert(graphMLXmlDocument != null);
        Debug.Assert(twitterUser != null);

        graphMLXmlDocument.AppendGraphMLAttributeValue(
            twitterUser.VertexXmlNode,
            VertexTweetedSearchTermID,
            userTweetedSearchTerm ? "Yes" : "No");
    }
    TryAddStatusToUser
    (
        Dictionary<String, Object> statusValueDictionary,
        TwitterUser twitterUser,
        Boolean expandStatusUrls
    )
    {
        Debug.Assert(statusValueDictionary != null);
        Debug.Assert(twitterUser != null);

		TwitterStatus twitterStatus;

		if ( !TwitterStatus.TryFromStatusValueDictionary(statusValueDictionary,
			expandStatusUrls, out twitterStatus) )
        {
            return (false);
        }

        twitterUser.Statuses.Add(twitterStatus);

        return (true);
    }
    TryAppendVertexXmlNode
    (
        Dictionary<String, Object> userValueDictionary,
        Boolean includeStatistics,
        Boolean userTweetedSearchTerm,
        GraphMLXmlDocument graphMLXmlDocument,
        Dictionary<String, TwitterUser> userIDDictionary,
        out TwitterUser twitterUser
    )
    {
        Debug.Assert(userValueDictionary != null);
        Debug.Assert(graphMLXmlDocument != null);
        Debug.Assert(userIDDictionary != null);

        twitterUser = null;

        String screenName, userID;

        if (
            !TwitterJsonUtil.TryGetJsonValueFromDictionary(userValueDictionary,
                "screen_name", out screenName)
            ||
            !TwitterJsonUtil.TryGetJsonValueFromDictionary(userValueDictionary,
                "id_str", out userID)
            )
        {
            return (false);
        }

        screenName = screenName.ToLower();

        Boolean isFirstTweetForAuthor =
            TwitterGraphMLUtil.TryAppendVertexXmlNode(
                screenName, userID, graphMLXmlDocument, userIDDictionary,
                out twitterUser);

        if (isFirstTweetForAuthor)
        {
            TwitterGraphMLUtil.AppendCommonUserInformationFromValueDictionary(
                userValueDictionary, graphMLXmlDocument, twitterUser);

            if (includeStatistics)
            {
                TwitterGraphMLUtil.AppendUserStatisticsFromValueDictionary(
                    userValueDictionary, graphMLXmlDocument, twitterUser);
            }

            AppendTweetedSearchTermGraphMLAttributeValue(
                graphMLXmlDocument, twitterUser, userTweetedSearchTerm);
        }

        return (true);
    }