CreateGraphMLXmlDocument ( Boolean bIncludeAllStatistics ) { AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = new GraphMLXmlDocument(true); NodeXLGraphMLUtil.DefineVertexCustomMenuGraphMLAttributes( oGraphMLXmlDocument); NodeXLGraphMLUtil.DefineEdgeRelationshipGraphMLAttribute( oGraphMLXmlDocument); if (bIncludeAllStatistics) { oGraphMLXmlDocument.DefineGraphMLAttributes(false, "int", FriendsID, "Friends", SubscriptionsID, "People Subscribed To", SubscribersID, "Subscribers", VideosWatchedID, "Videos Watched", VideosUploadedID, "Videos Uploaded" ); oGraphMLXmlDocument.DefineVertexStringGraphMLAttributes( JoinedDateUtcID, "Joined YouTube Date (UTC)"); NodeXLGraphMLUtil.DefineVertexImageFileGraphMLAttribute( oGraphMLXmlDocument); } return(oGraphMLXmlDocument); }
AppendFriendOrFollowerEdgeXmlNode ( String sScreenName1, String sScreenName2, Boolean bAppendFriendEdgeXmlNode, GraphMLXmlDocument oGraphMLXmlDocument, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sScreenName1)); Debug.Assert(!String.IsNullOrEmpty(sScreenName2)); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oRequestStatistics != null); AssertValid(); // Don't use "friend" or "follower" terminology here, which can be // confusing. Instead, simply indicate who follows whom. XmlNode oEdgeXmlNode = NodeXLGraphMLUtil.AppendEdgeXmlNode( oGraphMLXmlDocument, bAppendFriendEdgeXmlNode ? sScreenName1 : sScreenName2, bAppendFriendEdgeXmlNode ? sScreenName2 : sScreenName1, "Follows" ); AppendStartTimeRelationshipDateUtcGraphMLAttributeValue( oGraphMLXmlDocument, oEdgeXmlNode, oRequestStatistics); }
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); } } } }
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); }
CreateGraphMLXmlDocument ( Boolean bIncludeSampleThumbnails ) { AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = new GraphMLXmlDocument(true); NodeXLGraphMLUtil.DefineVertexLabelGraphMLAttribute( oGraphMLXmlDocument); NodeXLGraphMLUtil.DefineVertexCustomMenuGraphMLAttributes( oGraphMLXmlDocument); if (bIncludeSampleThumbnails) { NodeXLGraphMLUtil.DefineVertexImageFileGraphMLAttribute( oGraphMLXmlDocument); } return(oGraphMLXmlDocument); }
GetUserNetworkRecursive ( String sUserName, WhatToInclude eWhatToInclude, Boolean bIncludeFriendsThisCall, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary <String, XmlNode> oUserNameDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sUserName)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserNameDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* * Here is what this method should do, based on the eNetworkLevel and * iRecursionLevel parameters. * * eNetworkLevel * |One | OnePointFive | Two * ---|------------------| ------------------| ----------------- * i 1 |Add all vertices. | Add all vertices. | Add all vertices. * R | | | * e |Add all edges. | Add all edges. | Add all edges. * c | | | * u |Do not recurse. | Recurse. | Recurse. * r | | | * s ---|------------------|-------------------|------------------ * i 2 |Impossible. | Do not add | Add all vertices. * o | | vertices. | * n | | | * L | | Add edges only if | Add all edges. * e | | vertices are | * v | | already included. | * e | | | * l | | Do not recurse. | Do not recurse. | | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); List <String> oUserNamesToRecurse = new List <String>(); ReportProgressForFriendsOrSubscriptions(sUserName, bIncludeFriendsThisCall); Boolean bThisUserAppended = false; // If the GraphMLXmlDocument already contains at least one vertex node, // then this is the second time that this method has been called, a // partial network has already been obtained, and most errors should // now be skipped. However, if none of the network has been obtained // yet, errors on page 1 should throw an immediate exception. Boolean bSkipMostPage1Errors = oGraphMLXmlDocument.HasVertexXmlNode; // The document consists of a single "feed" node with zero or more // "entry" child nodes. foreach (XmlNode oEntryXmlNode in EnumerateXmlNodes( GetFriendsOrSubscriptionsUrl(sUserName, bIncludeFriendsThisCall), "a:feed/a:entry", iMaximumPeoplePerRequest, bSkipMostPage1Errors, oRequestStatistics)) { XmlNamespaceManager oXmlNamespaceManager = CreateXmlNamespaceManager(oEntryXmlNode.OwnerDocument); String sOtherUserName; if (!XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "yt:username/text()", oXmlNamespaceManager, out sOtherUserName)) { continue; } if (!bThisUserAppended) { // Append a vertex node for this request's user. // // This used to be done after the foreach loop, which avoided // the need for a "bThisUserAppended" flag. That caused the // following bug: If a YouTube error occurred within // EnumerateXmlNodes() after some edges had been added, and the // user decided to import the resulting partial network, the // GraphML might contain edges that referenced "this user" // without containing a vertex for "this user." That is an // illegal state for GraphML, which the ExcelTemplate project // caught and reported as an error. TryAppendVertexXmlNode(sUserName, null, oGraphMLXmlDocument, oUserNameDictionary); bThisUserAppended = true; } Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); if (bNeedToAppendVertices) { if ( TryAppendVertexXmlNode(sOtherUserName, oEntryXmlNode, oGraphMLXmlDocument, oUserNameDictionary) && bNeedToRecurse ) { oUserNamesToRecurse.Add(sOtherUserName); } } if (bNeedToAppendVertices || oUserNameDictionary.ContainsKey(sOtherUserName)) { String sRelationship; if (bIncludeFriendsThisCall) { sRelationship = "Friend of"; } else { sRelationship = "Subscribes to"; String sSubscriptionType = null; if (XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "a:category[@scheme='http://gdata.youtube.com/schemas/" + "2007/subscriptiontypes.cat']/@term", oXmlNamespaceManager, out sSubscriptionType)) { sRelationship += " " + sSubscriptionType; } } NodeXLGraphMLUtil.AppendEdgeXmlNode(oGraphMLXmlDocument, sUserName, sOtherUserName, sRelationship); } } if (bNeedToRecurse) { foreach (String sUserNameToRecurse in oUserNamesToRecurse) { GetUserNetworkRecursive(sUserNameToRecurse, eWhatToInclude, bIncludeFriendsThisCall, eNetworkLevel, iMaximumPeoplePerRequest, 2, oGraphMLXmlDocument, oUserNameDictionary, oRequestStatistics); } } }