//************************************************************************* // Method: AppendFromUserXmlNodeCalled() // /// <summary> /// Checks whether <see cref="AppendFromUserXmlNode" /> has been called for /// a vertex XML node. /// </summary> /// /// <param name="oGraphMLXmlDocument"> /// GraphMLXmlDocument being populated. /// </param> /// /// <param name="oVertexXmlNode"> /// The vertex XML node to check. /// </param> /// /// <remarks> /// true if <see cref="AppendFromUserXmlNode" /> has been called for the /// vertex XML node. /// </remarks> //************************************************************************* protected Boolean AppendFromUserXmlNodeCalled( GraphMLXmlDocument oGraphMLXmlDocument, XmlNode oVertexXmlNode ) { Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oVertexXmlNode != null); XmlNamespaceManager oXmlNamespaceManager = oGraphMLXmlDocument.CreateXmlNamespaceManager("a"); // The FollowedID and LatestStatusID GraphML-attributes are appended // only by AppendFromUserXmlNode(), so if either is present, // AppendFromUserXmlNode() has been called. return ( oVertexXmlNode.SelectSingleNode( "a:data[@key='" + FollowedID + "']", oXmlNamespaceManager) != null || oVertexXmlNode.SelectSingleNode( "a:data[@key='" + LatestStatusID + "']", oXmlNamespaceManager) != null ); }
//************************************************************************* // Method: AppendRepliesToAndMentionsXmlNodes() // /// <summary> /// Appends edge XML nodes for replies-to and mentions relationships. /// </summary> /// /// <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="bIncludeRepliesToEdges"> /// true to append edges for replies-to relationships. /// </param> /// /// <param name="bIncludeMentionsEdges"> /// true to append edges for mentions relationships. /// </param> //************************************************************************* protected void AppendRepliesToAndMentionsXmlNodes( GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, TwitterVertex> oScreenNameDictionary, Boolean bIncludeRepliesToEdges, Boolean bIncludeMentionsEdges ) { Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oScreenNameDictionary != null); AssertValid(); if (!bIncludeRepliesToEdges && !bIncludeMentionsEdges) { return; } XmlNamespaceManager oGraphMLXmlNamespaceManager = oGraphMLXmlDocument.CreateXmlNamespaceManager("g"); ReportProgress("Examining relationships."); // "Starts with a screen name," which means it's a "reply-to". Regex oReplyToRegex = new Regex(@"^@(?<ScreenName>\w+)"); // "Contains a screen name," which means it's a "mentions". // // Note that a "reply-to" is also a "mentions." Regex oMentionsRegex = new Regex(@"(^|\s)@(?<ScreenName>\w+)"); foreach (KeyValuePair<String, TwitterVertex> oKeyValuePair in oScreenNameDictionary) { String sScreenName = oKeyValuePair.Key; TwitterVertex oTwitterVertex = oKeyValuePair.Value; String sStatusForAnalysis = oTwitterVertex.StatusForAnalysis; String sStatusForAnalysisDateUtc = oTwitterVertex.StatusForAnalysisDateUtc; if ( String.IsNullOrEmpty(sStatusForAnalysis) ) { continue; } if (bIncludeRepliesToEdges) { Match oReplyToMatch = oReplyToRegex.Match(sStatusForAnalysis); if (oReplyToMatch.Success) { String sReplyToScreenName = oReplyToMatch.Groups["ScreenName"].Value.ToLower(); if ( sReplyToScreenName != sScreenName && oScreenNameDictionary.ContainsKey(sReplyToScreenName) ) { XmlNode oEdgeXmlNode = AppendEdgeXmlNode( oGraphMLXmlDocument, sScreenName, sReplyToScreenName, "Replies to"); if ( !String.IsNullOrEmpty(sStatusForAnalysisDateUtc) ) { oGraphMLXmlDocument.AppendGraphMLAttributeValue( oEdgeXmlNode, RelationshipDateUtcID, sStatusForAnalysisDateUtc); } } } } if (bIncludeMentionsEdges) { Match oMentionsMatch = oMentionsRegex.Match(sStatusForAnalysis); while (oMentionsMatch.Success) { String sMentionsScreenName = oMentionsMatch.Groups["ScreenName"].Value.ToLower(); if ( sMentionsScreenName != sScreenName && oScreenNameDictionary.ContainsKey(sMentionsScreenName) ) { XmlNode oEdgeXmlNode = AppendEdgeXmlNode( oGraphMLXmlDocument, sScreenName, sMentionsScreenName, "Mentions"); if ( !String.IsNullOrEmpty(sStatusForAnalysisDateUtc) ) { oGraphMLXmlDocument.AppendGraphMLAttributeValue( oEdgeXmlNode, RelationshipDateUtcID, sStatusForAnalysisDateUtc); } } oMentionsMatch = oMentionsMatch.NextMatch(); } } } }
//************************************************************************* // 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); } }