CreateGraphMLXmlDocument ( Boolean includeStatistics, Boolean includeStatuses ) { GraphMLXmlDocument graphMLXmlDocument = new GraphMLXmlDocument(true); if (includeStatistics) { TwitterGraphMLUtil.DefineVertexStatisticsGraphMLAttributes( graphMLXmlDocument); } TwitterGraphMLUtil.DefineCommonGraphMLAttributes(graphMLXmlDocument); graphMLXmlDocument.DefineVertexStringGraphMLAttributes( VertexTweetedSearchTermID, "Tweeted Search Term?"); graphMLXmlDocument.DefineVertexStringGraphMLAttributes( VertexToolTipID, "Tooltip"); if (includeStatuses) { TwitterGraphMLUtil.DefineEdgeStatusGraphMLAttributes( graphMLXmlDocument); } return (graphMLXmlDocument); }
DefineVertexImageFileGraphMLAttribute ( GraphMLXmlDocument graphMLXmlDocument ) { Debug.Assert(graphMLXmlDocument != null); graphMLXmlDocument.DefineVertexStringGraphMLAttributes( VertexImageFileID, VertexImageFileColumnName); }
DefineVertexLabelGraphMLAttribute ( GraphMLXmlDocument graphMLXmlDocument ) { Debug.Assert(graphMLXmlDocument != null); graphMLXmlDocument.DefineVertexStringGraphMLAttributes( VertexLabelID, VertexLabelColumnName); }
DefineEdgeRelationshipGraphMLAttribute ( GraphMLXmlDocument graphMLXmlDocument ) { Debug.Assert(graphMLXmlDocument != null); graphMLXmlDocument.DefineEdgeStringGraphMLAttributes( EdgeRelationshipID, "Relationship"); }
DefineVertexLatestStatusGraphMLAttributes ( GraphMLXmlDocument graphMLXmlDocument ) { Debug.Assert(graphMLXmlDocument != null); graphMLXmlDocument.DefineVertexStringGraphMLAttributes( VertexLatestStatusID, "Latest Tweet", VertexLatestStatusUrlsID, "URLs in Latest Tweet", VertexLatestStatusDomainsID, "Domains in Latest Tweet", VertexLatestStatusHashtagsID, "Hashtags in Latest Tweet", VertexLatestStatusDateUtcID, "Latest Tweet Date (UTC)" ); DefineLatitudeAndLongitudeGraphMLAttributes(graphMLXmlDocument, false); DefineInReplyToStatusIDGraphMLAttribute(graphMLXmlDocument, false); }
DefineVertexStatisticsGraphMLAttributes ( GraphMLXmlDocument graphMLXmlDocument ) { Debug.Assert(graphMLXmlDocument != null); graphMLXmlDocument.DefineGraphMLAttributes(false, "int", VertexFollowedID, "Followed", VertexFollowersID, "Followers", VertexStatusesID, "Tweets", VertexFavoritesID, "Favorites", VertexUtcOffsetID, "Time Zone UTC Offset (Seconds)" ); graphMLXmlDocument.DefineVertexStringGraphMLAttributes( VertexDescriptionID, "Description", VertexLocationID, "Location", VertexUrlID, "Web", VertexTimeZoneID, "Time Zone", VertexJoinedDateUtcID, "Joined Twitter Date (UTC)" ); }
AppendSharedResponderEdges ( GraphMLXmlDocument oGraphMLXmlDocument, HashSet<String> oVideoIDs, Int32 iMaximumResponses, String sUrlPattern, String sResponderTitle, String sKeyAttributeID, RequestStatistics oRequestStatistics ) { Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oVideoIDs != null); Debug.Assert(iMaximumResponses > 0); Debug.Assert( !String.IsNullOrEmpty(sUrlPattern) ); Debug.Assert(sUrlPattern.IndexOf("{0}") >= 0); Debug.Assert( !String.IsNullOrEmpty(sResponderTitle) ); Debug.Assert( !String.IsNullOrEmpty(sKeyAttributeID) ); Debug.Assert(oRequestStatistics != null); AssertValid(); // The key is the name of an author and the value is a LinkedList of // the video IDs to which the author has responded. Dictionary< String, LinkedList<String> > oAuthorUserNameDictionary = new Dictionary< String, LinkedList<String> >(); foreach (String sVideoID in oVideoIDs) { ReportProgress(String.Format( "Getting {0}s for the video with the ID \"{1}\"." , sResponderTitle, sVideoID ) ); // This is to prevent self-loop edges that would result when the // same author responds to the same video more than once. HashSet<String> oAuthorUserNames = new HashSet<String>(); String sUrl = String.Format(sUrlPattern, sVideoID); // The document consists of an "entry" XML node for each response. foreach ( XmlNode oEntryXmlNode in EnumerateXmlNodes(sUrl, "a:feed/a:entry", iMaximumResponses, true, oRequestStatistics) ) { XmlNamespaceManager oXmlNamespaceManager = CreateXmlNamespaceManager(oEntryXmlNode.OwnerDocument); String sAuthorUserName; if ( XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "a:author/a:name/text()", oXmlNamespaceManager, out sAuthorUserName) && !oAuthorUserNames.Contains(sAuthorUserName) ) { AddVideoIDToDictionary(sAuthorUserName, sVideoID, oAuthorUserNameDictionary); oAuthorUserNames.Add(sAuthorUserName); } } } ReportProgress("Adding edges for shared " + sResponderTitle + "s."); AppendEdgesFromDictionary(oAuthorUserNameDictionary, oGraphMLXmlDocument, "Shared " + sResponderTitle, sKeyAttributeID); }
CreateGraphMLXmlDocument ( WhatToInclude eWhatToInclude ) { AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = new GraphMLXmlDocument(false); NodeXLGraphMLUtil.DefineEdgeRelationshipGraphMLAttribute( oGraphMLXmlDocument); if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedCategoryEdges) ) { oGraphMLXmlDocument.DefineEdgeStringGraphMLAttributes( SharedCategoryID, "Shared Category"); } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedCommenterEdges) ) { oGraphMLXmlDocument.DefineEdgeStringGraphMLAttributes( SharedCommenterID, "Shared Commenter"); } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedVideoResponderEdges) ) { oGraphMLXmlDocument.DefineEdgeStringGraphMLAttributes( SharedVideoResponderID, "Shared Video Responder"); } oGraphMLXmlDocument.DefineVertexStringGraphMLAttributes( TitleID, "Title", AuthorID, "Author", CreatedDateUtcID, "Created Date (UTC)" ); oGraphMLXmlDocument.DefineGraphMLAttribute(false, RatingID, "Rating", "double", null); oGraphMLXmlDocument.DefineGraphMLAttributes(false, "int", ViewsID, "Views", FavoritedID, "Favorited", CommentsID, "Comments" ); NodeXLGraphMLUtil.DefineVertexImageFileGraphMLAttribute( oGraphMLXmlDocument); NodeXLGraphMLUtil.DefineVertexCustomMenuGraphMLAttributes( oGraphMLXmlDocument); return (oGraphMLXmlDocument); }
AppendVertexXmlNodes ( String sSearchTerm, WhatToInclude eWhatToInclude, Int32 iMaximumVideos, GraphMLXmlDocument oGraphMLXmlDocument, RequestStatistics oRequestStatistics, out HashSet<String> oVideoIDs, out Dictionary< String, LinkedList<String> > oCategoryDictionary ) { Debug.Assert( !String.IsNullOrEmpty(sSearchTerm) ); Debug.Assert(iMaximumVideos> 0); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oRequestStatistics != null); AssertValid(); ReportProgress("Getting a list of videos."); // This is used to skip duplicate videos in the results returned by // YouTube. (I'm not sure why YouTube sometimes returns duplicates, // but it does.) oVideoIDs = new HashSet<String>(); // If an edge should be included for each pair of videos that share the // same category, the key is a lower-case category and the value is a // LinkedList of the video IDs that have the category. if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedCategoryEdges) ) { oCategoryDictionary = new Dictionary< String, LinkedList<String> >(); } else { oCategoryDictionary = null; } String sUrl = String.Format( "http://gdata.youtube.com/feeds/api/videos?q={0}" , EncodeUrlParameter(sSearchTerm) ); // The document consists of an "entry" XML node for each video. foreach ( XmlNode oEntryXmlNode in EnumerateXmlNodes(sUrl, "a:feed/a:entry", iMaximumVideos, false, oRequestStatistics) ) { XmlNamespaceManager oXmlNamespaceManager = CreateXmlNamespaceManager(oEntryXmlNode.OwnerDocument); // Use the video ID as the GraphML vertex name. The video title // can't be used because it is not unique. String sVideoID; if ( !XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "media:group/yt:videoid/text()", oXmlNamespaceManager, out sVideoID) || oVideoIDs.Contains(sVideoID) ) { continue; } oVideoIDs.Add(sVideoID); XmlNode oVertexXmlNode = oGraphMLXmlDocument.AppendVertexXmlNode( sVideoID); AppendStringGraphMLAttributeValue(oEntryXmlNode, "a:title/text()", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, TitleID); AppendStringGraphMLAttributeValue(oEntryXmlNode, "a:author/a:name/text()", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, AuthorID); AppendDoubleGraphMLAttributeValue(oEntryXmlNode, "gd:rating/@average", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, RatingID); AppendInt32GraphMLAttributeValue(oEntryXmlNode, "yt:statistics/@viewCount", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, ViewsID); AppendInt32GraphMLAttributeValue(oEntryXmlNode, "yt:statistics/@favoriteCount", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, FavoritedID); AppendInt32GraphMLAttributeValue(oEntryXmlNode, "gd:comments/gd:feedLink/@countHint", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, CommentsID); AppendYouTubeDateGraphMLAttributeValue(oEntryXmlNode, "a:published/text()", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, CreatedDateUtcID); AppendStringGraphMLAttributeValue(oEntryXmlNode, "media:group/media:thumbnail/@url", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, NodeXLGraphMLUtil.VertexImageFileID); if ( AppendStringGraphMLAttributeValue(oEntryXmlNode, "media:group/media:player/@url", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, NodeXLGraphMLUtil.VertexMenuActionID) ) { oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode, NodeXLGraphMLUtil.VertexMenuTextID, "Play Video in Browser"); } if (oCategoryDictionary != null) { CollectCategories(oEntryXmlNode, sVideoID, oXmlNamespaceManager, oCategoryDictionary); } } }
DefineLabelGraphMLAttribute ( GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); oGraphMLXmlDocument.DefineGraphMLAttribute(false, LabelID, LabelColumnName, "string", null); }
GetVideoNetworkInternal ( String sSearchTerm, WhatToInclude eWhatToInclude, Int32 iMaximumVideos, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sSearchTerm) ); Debug.Assert(iMaximumVideos > 0); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // First, add a vertex for each video matching the search term. HashSet<String> oVideoIDs; Dictionary< String, LinkedList<String> > oCategoryDictionary; AppendVertexXmlNodes(sSearchTerm, eWhatToInclude, iMaximumVideos, oGraphMLXmlDocument, oRequestStatistics, out oVideoIDs, out oCategoryDictionary); // Now add whatever edges were requested. if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedCategoryEdges) ) { Debug.Assert(oCategoryDictionary != null); ReportProgress("Adding edges for shared categories."); AppendEdgesFromDictionary(oCategoryDictionary, oGraphMLXmlDocument, "Shared category", SharedCategoryID); } oCategoryDictionary = null; if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedCommenterEdges) ) { AppendSharedResponderEdges(oGraphMLXmlDocument, oVideoIDs, MaximumCommentsPerVideo, "http://gdata.youtube.com/feeds/api/videos/{0}/comments", "commenter", SharedCommenterID, oRequestStatistics); } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedVideoResponderEdges) ) { AppendSharedResponderEdges(oGraphMLXmlDocument, oVideoIDs, iMaximumVideos, "http://gdata.youtube.com/feeds/api/videos/{0}/responses", "video responder", SharedVideoResponderID, oRequestStatistics); } }
DefineImportedIDGraphMLAttribute ( GraphMLXmlDocument graphMLXmlDocument, Boolean forEdges ) { Debug.Assert(graphMLXmlDocument != null); graphMLXmlDocument.DefineStringGraphMLAttributes(forEdges, ImportedIDID, "Imported ID"); }
AppendVertexXmlNode ( String sScreenName, String sUserID, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, TwitterUser> oUserIDDictionary, Dictionary<String, Object> oUserValueDictionary, Boolean bIncludeStatistics, Boolean bIncludeLatestStatus, Boolean bExpandLatestStatusUrls ) { Debug.Assert( !String.IsNullOrEmpty(sScreenName) ); Debug.Assert( !String.IsNullOrEmpty(sUserID) ); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserIDDictionary != null); Debug.Assert(oUserValueDictionary != null); AssertValid(); TwitterUser oTwitterUser; TwitterGraphMLUtil.TryAppendVertexXmlNode(sScreenName, sUserID, oGraphMLXmlDocument, oUserIDDictionary, out oTwitterUser); AppendUserInformationFromValueDictionary(oUserValueDictionary, oGraphMLXmlDocument, oTwitterUser, bIncludeStatistics, bIncludeLatestStatus, bExpandLatestStatusUrls); }
AppendVertexXmlNodesForSearchTerm ( String sSearchTerm, WhatToInclude eWhatToInclude, Int32 iMaximumStatuses, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, TwitterUser> oUserIDDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert( !String.IsNullOrEmpty(sSearchTerm) ); Debug.Assert(iMaximumStatuses > 0); Debug.Assert(iMaximumStatuses != Int32.MaxValue); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserIDDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); Boolean bExpandStatusUrls = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.ExpandedStatusUrls); Boolean bIncludeStatistics = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.Statistics); ReportProgress("Getting a list of tweets."); // Get the tweets that contain the search term. Note that multiple // tweets may have the same author. Debug.Assert(m_oTwitterUtil != null); foreach ( Dictionary<String, Object> oStatusValueDictionary in m_oTwitterUtil.EnumerateSearchStatuses( sSearchTerm, iMaximumStatuses, oRequestStatistics, new ReportProgressHandler(this.ReportProgress), new CheckCancellationPendingHandler( this.CheckCancellationPending) ) ) { const String UserKeyName = "user"; if ( !oStatusValueDictionary.ContainsKey(UserKeyName) ) { // This has actually happened--Twitter occasionally sends a // status without user information. continue; } Dictionary<String, Object> oUserValueDictionary = ( Dictionary<String, Object> ) oStatusValueDictionary[UserKeyName]; TwitterUser oTwitterUser; if ( !TwitterSearchNetworkGraphMLUtil. TryAppendVertexXmlNode(oUserValueDictionary, bIncludeStatistics, true, oGraphMLXmlDocument, oUserIDDictionary, out oTwitterUser) ) { continue; } // Parse the status and add it to the user's status collection. if ( !TwitterSearchNetworkGraphMLUtil.TryAddStatusToUser( oStatusValueDictionary, oTwitterUser, bExpandStatusUrls) ) { continue; } } }
OnNetworkObtainedWithoutTerminatingException ( GraphMLXmlDocument oGraphMLXmlDocument, RequestStatistics oRequestStatistics, String sNetworkDescription ) { Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oRequestStatistics != null); Debug.Assert( !String.IsNullOrEmpty(sNetworkDescription) ); AssertValid(); XmlUtil2.SetAttributes(oGraphMLXmlDocument.GraphXmlNode, "description", sNetworkDescription); if (oRequestStatistics.UnexpectedExceptions > 0) { // The network is partial. throw new PartialNetworkException(oGraphMLXmlDocument, oRequestStatistics); } }
AppendEdgeXmlNode ( GraphMLXmlDocument oGraphMLXmlDocument, String sVertex1ID, String sVertex2ID, String sRelationship ) { Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert( !String.IsNullOrEmpty(sVertex1ID) ); Debug.Assert( !String.IsNullOrEmpty(sVertex2ID) ); Debug.Assert( !String.IsNullOrEmpty(sRelationship) ); AssertValid(); XmlNode oEdgeXmlNode = oGraphMLXmlDocument.AppendEdgeXmlNode( sVertex1ID, sVertex2ID); oGraphMLXmlDocument.AppendGraphMLAttributeValue(oEdgeXmlNode, RelationshipID, sRelationship); return (oEdgeXmlNode); }
GetNetworkInternal ( String sSearchTerm, WhatToInclude eWhatToInclude, Int32 iMaximumStatuses, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sSearchTerm) ); Debug.Assert(iMaximumStatuses > 0); Debug.Assert(iMaximumStatuses != Int32.MaxValue); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // The key is the Twitter user ID and the value is the corresponding // TwitterUser. Dictionary<String, TwitterUser> oUserIDDictionary = new Dictionary<String, TwitterUser>(); // First, append a vertex for each person who has tweeted the search // term. AppendVertexXmlNodesForSearchTerm(sSearchTerm, eWhatToInclude, iMaximumStatuses, oGraphMLXmlDocument, oUserIDDictionary, oRequestStatistics); // Now append a vertex for each person who was mentioned or replied to // by the first set of people, but who didn't tweet the search term // himself. AppendVertexXmlNodesForMentionsAndRepliesTo(eWhatToInclude, oGraphMLXmlDocument, oUserIDDictionary, oRequestStatistics); TwitterSearchNetworkGraphMLUtil.AppendVertexTooltipXmlNodes( oGraphMLXmlDocument, oUserIDDictionary); if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedEdges) ) { // Look at the people followed by each author, and if a followed // has also tweeted the search term, add an edge between the author // and the followed. AppendFollowedOrFollowingEdgeXmlNodes(oUserIDDictionary, true, MaximumFollowers, oGraphMLXmlDocument, oRequestStatistics); } AppendRepliesToAndMentionsEdgeXmlNodes(oGraphMLXmlDocument, oUserIDDictionary.Values, TwitterGraphMLUtil.TwitterUsersToUniqueScreenNames( oUserIDDictionary.Values), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.RepliesToEdges), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.MentionsEdges), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.NonRepliesToNonMentionsEdges), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.Statuses) ); }
AppendDoubleGraphMLAttributeValue ( XmlNode oXmlNodeToSelectFrom, String sXPath, XmlNamespaceManager oXmlNamespaceManager, GraphMLXmlDocument oGraphMLXmlDocument, XmlNode oEdgeOrVertexXmlNode, String sGraphMLAttributeID ) { Debug.Assert(oXmlNodeToSelectFrom != null); Debug.Assert( !String.IsNullOrEmpty(sXPath) ); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oEdgeOrVertexXmlNode != null); Debug.Assert( !String.IsNullOrEmpty(sGraphMLAttributeID) ); AssertValid(); Double dAttributeValue; if ( XmlUtil2.TrySelectSingleNodeAsDouble(oXmlNodeToSelectFrom, sXPath, oXmlNamespaceManager, out dAttributeValue) ) { oGraphMLXmlDocument.AppendGraphMLAttributeValue( oEdgeOrVertexXmlNode, sGraphMLAttributeID, dAttributeValue); return (true); } return (false); }
DefineRelationshipGraphMLAttribute ( GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); oGraphMLXmlDocument.DefineGraphMLAttribute(true, RelationshipID, "Relationship", "string", null); }
DefineCustomMenuGraphMLAttributes ( GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); oGraphMLXmlDocument.DefineGraphMLAttribute(false, MenuTextID, MenuTextColumnName, "string", null); oGraphMLXmlDocument.DefineGraphMLAttribute(false, MenuActionID, MenuActionColumnName, "string", null); }
AppendEdgesFromDictionary ( Dictionary< String, LinkedList<String> > oDictionary, GraphMLXmlDocument oGraphMLXmlDocument, String sRelationship, String sKeyAttributeID ) { Debug.Assert(oDictionary != null); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert( !String.IsNullOrEmpty(sRelationship) ); Debug.Assert( !String.IsNullOrEmpty(sKeyAttributeID) ); AssertValid(); // For each key... foreach (KeyValuePair< String, LinkedList<String> > oKeyValuePair in oDictionary) { String sKey = oKeyValuePair.Key; // For each video ID that has the key... LinkedList<String> oVideoIDsWithThisKey = oKeyValuePair.Value; for ( LinkedListNode<String> oVideoIDWithThisKey = oVideoIDsWithThisKey.First; oVideoIDWithThisKey != null; oVideoIDWithThisKey = oVideoIDWithThisKey.Next ) { // For each of the subsequent video IDs in the LinkedList that // have the key... for ( LinkedListNode<String> oSubsequentVideoIDWithThisKey = oVideoIDWithThisKey.Next; oSubsequentVideoIDWithThisKey != null; oSubsequentVideoIDWithThisKey = oSubsequentVideoIDWithThisKey.Next ) { XmlNode oEdgeXmlNode = NodeXLGraphMLUtil.AppendEdgeXmlNode( oGraphMLXmlDocument, oVideoIDWithThisKey.Value, oSubsequentVideoIDWithThisKey.Value, sRelationship); oGraphMLXmlDocument.AppendGraphMLAttributeValue( oEdgeXmlNode, sKeyAttributeID, sKey); } } } }
AppendVertexXmlNodes ( Boolean bUseListName, String sListName, ICollection<String> oScreenNames, WhatToInclude eWhatToInclude, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, TwitterUser> oUserIDDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert( !bUseListName || !String.IsNullOrEmpty(sListName) ); Debug.Assert(bUseListName || oScreenNames != null); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserIDDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); Boolean bIncludeStatistics = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.Statistics); Boolean bIncludeLatestStatuses = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.LatestStatuses); Boolean bExpandLatestStatusUrls = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.ExpandedLatestStatusUrls); String sUserID; if (bUseListName) { String sSlug, sOwnerScreenName; if ( !TryParseListName(sListName, out sSlug, out sOwnerScreenName) ) { return; } String sUrl = String.Format( "{0}lists/members.json?slug={1}&owner_screen_name={2}&{3}" , TwitterApiUrls.Rest, TwitterUtil.EncodeUrlParameter(sSlug), TwitterUtil.EncodeUrlParameter(sOwnerScreenName), TwitterApiUrlParameters.IncludeEntities ); // The JSON contains a "users" array for the users in the Twitter // list. foreach ( Object oResult in EnumerateJsonValues(sUrl, "users", Int32.MaxValue, false, oRequestStatistics) ) { String sScreenName; Dictionary<String, Object> oUserValueDictionary = ( Dictionary<String, Object> )oResult; if ( TryGetScreenNameFromDictionary(oUserValueDictionary, out sScreenName) && TryGetUserIDFromDictionary(oUserValueDictionary, out sUserID) ) { AppendVertexXmlNode(sScreenName, sUserID, oGraphMLXmlDocument, oUserIDDictionary, oUserValueDictionary, bIncludeStatistics, bIncludeLatestStatuses, bExpandLatestStatusUrls); } } } else { // Eliminate duplicate names. HashSet<String> oUniqueScreenNames = new HashSet<String>(); foreach (String sScreenName in oScreenNames) { oUniqueScreenNames.Add( sScreenName.ToLower() ); } foreach (String sScreenName in oUniqueScreenNames) { Dictionary<String, Object> oUserValueDictionary; if ( TryGetUserValueDictionary(sScreenName, oRequestStatistics, true, out oUserValueDictionary) && TryGetUserIDFromDictionary(oUserValueDictionary, out sUserID) ) { AppendVertexXmlNode(sScreenName, sUserID, oGraphMLXmlDocument, oUserIDDictionary, oUserValueDictionary, bIncludeStatistics, bIncludeLatestStatuses, bExpandLatestStatusUrls); } } } }
DefineVertexCustomMenuGraphMLAttributes ( GraphMLXmlDocument graphMLXmlDocument ) { Debug.Assert(graphMLXmlDocument != null); graphMLXmlDocument.DefineVertexStringGraphMLAttributes( VertexMenuTextID, VertexMenuTextColumnName, VertexMenuActionID, VertexMenuActionColumnName ); }
SaveGraphCore ( IGraph graph, Stream stream ) { Debug.Assert(graph != null); Debug.Assert(stream != null); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = new GraphMLXmlDocument( graph.Directedness == GraphDirectedness.Directed); String [] asEdgeAttributeNames = GetAttributeNames(graph, false); String [] asVertexAttributeNames = GetAttributeNames(graph, true); // Define the GraphML-attributes. const String VertexAttributeIDPrefix = "V-"; const String EdgeAttributeIDPrefix = "E-"; foreach (String sVertexAttributeName in asVertexAttributeNames) { oGraphMLXmlDocument.DefineGraphMLAttribute(false, VertexAttributeIDPrefix + sVertexAttributeName, sVertexAttributeName, "string", null); } foreach (String sEdgeAttributeName in asEdgeAttributeNames) { oGraphMLXmlDocument.DefineGraphMLAttribute(true, EdgeAttributeIDPrefix + sEdgeAttributeName, sEdgeAttributeName, "string", null); } // Add the vertices and their GraphML-attribute values. foreach (IVertex oVertex in graph.Vertices) { XmlNode oVertexXmlNode = oGraphMLXmlDocument.AppendVertexXmlNode( oVertex.Name); AppendGraphMLAttributeValues(oVertex, oGraphMLXmlDocument, oVertexXmlNode, asVertexAttributeNames, VertexAttributeIDPrefix); } // Add the edges and their GraphML-attribute values. foreach (IEdge oEdge in graph.Edges) { IVertex [] oVertices = oEdge.Vertices; XmlNode oEdgeXmlNode = oGraphMLXmlDocument.AppendEdgeXmlNode( oVertices[0].Name, oVertices[1].Name); AppendGraphMLAttributeValues(oEdge, oGraphMLXmlDocument, oEdgeXmlNode, asEdgeAttributeNames, EdgeAttributeIDPrefix); } oGraphMLXmlDocument.Save(stream); }
AppendEdgeXmlNode ( GraphMLXmlDocument graphMLXmlDocument, String vertex1ID, String vertex2ID, String relationship ) { Debug.Assert(graphMLXmlDocument != null); Debug.Assert( !String.IsNullOrEmpty(vertex1ID) ); Debug.Assert( !String.IsNullOrEmpty(vertex2ID) ); Debug.Assert( !String.IsNullOrEmpty(relationship) ); XmlNode edgeXmlNode = graphMLXmlDocument.AppendEdgeXmlNode( vertex1ID, vertex2ID); graphMLXmlDocument.AppendGraphMLAttributeValue(edgeXmlNode, EdgeRelationshipID, relationship); return (edgeXmlNode); }
AppendGraphMLAttributeValues ( IMetadataProvider oEdgeOrVertex, GraphMLXmlDocument oGraphMLXmlDocument, XmlNode oEdgeOrVertexXmlNode, String [] asAttributeNames, String AttributeIDPrefix ) { Debug.Assert(oEdgeOrVertex != null); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oEdgeOrVertexXmlNode != null); Debug.Assert(asAttributeNames != null); Debug.Assert( !String.IsNullOrEmpty(AttributeIDPrefix) ); AssertValid(); foreach (String sAttributeName in asAttributeNames) { Object oAttributeValue; // Note that the value type isn't checked. Whatever type it is, // it gets converted to a string. if (oEdgeOrVertex.TryGetValue(sAttributeName, out oAttributeValue) && oAttributeValue != null) { oGraphMLXmlDocument.AppendGraphMLAttributeValue( oEdgeOrVertexXmlNode, AttributeIDPrefix + sAttributeName, oAttributeValue.ToString() ); } } }
AppendVertexXmlNodesForMentionsAndRepliesTo ( WhatToInclude eWhatToInclude, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, TwitterUser> oUserIDDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserIDDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); ReportProgress("Getting replied to and mentioned users."); // Get the screen names that were mentioned or replied to by the people // who tweeted the search term. String[] asUniqueMentionsAndRepliesToScreenNames = TwitterSearchNetworkGraphMLUtil.GetMentionsAndRepliesToScreenNames( oUserIDDictionary); Boolean bIncludeStatistics = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.Statistics); // Get information about each of those screen names and append vertex // XML nodes for them if necessary. foreach ( Dictionary<String, Object> oUserValueDictionary in EnumerateUserValueDictionaries( asUniqueMentionsAndRepliesToScreenNames, false, oRequestStatistics) ) { TwitterUser oTwitterUser; TwitterSearchNetworkGraphMLUtil.TryAppendVertexXmlNode( oUserValueDictionary, bIncludeStatistics, false, oGraphMLXmlDocument, oUserIDDictionary, out oTwitterUser); } }
DefineImageFileGraphMLAttribute ( GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); oGraphMLXmlDocument.DefineGraphMLAttribute(false, ImageFileID, ImageColumnName, "string", null); }
AppendYouTubeDateGraphMLAttributeValue ( XmlNode oXmlNodeToSelectFrom, String sXPath, XmlNamespaceManager oXmlNamespaceManager, GraphMLXmlDocument oGraphMLXmlDocument, XmlNode oVertexXmlNode, String sGraphMLAttributeID ) { Debug.Assert(oXmlNodeToSelectFrom != null); Debug.Assert( !String.IsNullOrEmpty(sXPath) ); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oVertexXmlNode != null); Debug.Assert( !String.IsNullOrEmpty(sGraphMLAttributeID) ); AssertValid(); String sYouTubeDate; if ( XmlUtil2.TrySelectSingleNodeAsString(oXmlNodeToSelectFrom, sXPath, oXmlNamespaceManager, out sYouTubeDate) ) { oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode, sGraphMLAttributeID, FormatYouTubeDate(sYouTubeDate) ); return (true); } return (false); }
GetNetworkDescription ( String sSearchTerm, WhatToInclude eWhatToInclude, Int32 iMaximumStatuses, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sSearchTerm) ); Debug.Assert(iMaximumStatuses > 0); Debug.Assert(iMaximumStatuses != Int32.MaxValue); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); const String Int32FormatString = "N0"; NetworkDescriber oNetworkDescriber = new NetworkDescriber(); Int32 iVertexXmlNodes = oGraphMLXmlDocument.VertexXmlNodes; oNetworkDescriber.AddSentence( // WARNING: // // If you change this first sentence, you may also have to change // the code in // TwitterSearchNetworkTopItemsCalculator2.GetSearchTerm(), which // attempts to extract the search term from the graph description. "The graph represents a network of {0} Twitter {1} whose recent" + " tweets contained \"{2}\", or who {3} replied to or mentioned" + " in those tweets, taken from a data set limited to a maximum of" + " {4} tweets." , iVertexXmlNodes.ToString(Int32FormatString), StringUtil.MakePlural("user", iVertexXmlNodes), sSearchTerm, iVertexXmlNodes > 1 ? "were" : "was", iMaximumStatuses.ToString(Int32FormatString) ); oNetworkDescriber.AddNetworkTime(NetworkSource); Boolean bIncludeFollowedEdges = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedEdges); Boolean bIncludeRepliesToEdges = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.RepliesToEdges); Boolean bIncludeMentionsEdges = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.MentionsEdges); Boolean bIncludeNonRepliesToNonMentionsEdges = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.NonRepliesToNonMentionsEdges); if (bIncludeRepliesToEdges && bIncludeMentionsEdges && bIncludeNonRepliesToNonMentionsEdges) { // Every collected tweet has an edge that contains the date of the // tweet, so the range of tweet dates can be determined. oNetworkDescriber.StartNewParagraph(); TweetDateRangeAnalyzer.AddTweetDateRangeToNetworkDescription( oGraphMLXmlDocument, oNetworkDescriber); } if (bIncludeFollowedEdges || bIncludeRepliesToEdges || bIncludeMentionsEdges || bIncludeNonRepliesToNonMentionsEdges) { oNetworkDescriber.StartNewParagraph(); } if (bIncludeFollowedEdges) { oNetworkDescriber.AddSentence( "There is an edge for each follows relationship." ); } if (bIncludeRepliesToEdges) { oNetworkDescriber.AddSentence( "There is an edge for each \"replies-to\" relationship in a" + " tweet." ); } if (bIncludeMentionsEdges) { oNetworkDescriber.AddSentence( "There is an edge for each \"mentions\" relationship in a" + " tweet." ); } if (bIncludeNonRepliesToNonMentionsEdges) { oNetworkDescriber.AddSentence( "There is a self-loop edge for each tweet that is not a" + " \"replies-to\" or \"mentions\"." ); } return ( oNetworkDescriber.ConcatenateSentences() ); }