//************************************************************************* // Method: AppendVertexXmlNodes() // /// <summary> /// Appends a vertex XML node for each video that matches a specified /// search term. /// </summary> /// /// <param name="sSearchTerm"> /// The term to search for. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="iMaximumVideos"> /// Maximum number of videos to request, or Int32.MaxValue for no limit. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// The GraphMLXmlDocument being populated. /// </param> /// /// <param name="oRequestStatistics"> /// A <see cref="RequestStatistics" /> object that is keeping track of /// requests made while getting the network. /// </param> /// /// <param name="oVideoIDs"> /// Where the set of unique video IDs gets stored. /// </param> /// /// <param name="oTagDictionary"> /// If an edge should be included for each pair of videos that share the /// same tag, this gets set to a Dictionary for which the key is a /// lower-case tag and the value is a LinkedList of the video IDs that have /// the tag. Otherwise, it gets set to null. /// </param> //************************************************************************* protected void AppendVertexXmlNodes( String sSearchTerm, WhatToInclude eWhatToInclude, Int32 iMaximumVideos, GraphMLXmlDocument oGraphMLXmlDocument, RequestStatistics oRequestStatistics, out HashSet<String> oVideoIDs, out Dictionary< String, LinkedList<String> > oTagDictionary ) { 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 tag, the key is a lower-case tag and the value is a LinkedList // of the video IDs that have the tag. if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SharedTagEdges) ) { oTagDictionary = new Dictionary< String, LinkedList<String> >(); } else { oTagDictionary = 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); 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, ImageFileID); if ( AppendStringGraphMLAttributeValue(oEntryXmlNode, "media:group/media:player/@url", oXmlNamespaceManager, oGraphMLXmlDocument, oVertexXmlNode, MenuActionID) ) { oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode, MenuTextID, "Play Video in Browser"); } if (oTagDictionary != null) { CollectTags(oEntryXmlNode, sVideoID, oXmlNamespaceManager, oTagDictionary); } } }
//************************************************************************* // Method: AppendVertexXmlNode() // /// <summary> /// Appends a vertex XML node to the document for a tag if such a node /// doesn't already exist. /// </summary> /// /// <param name="sTag"> /// Tag to add a vertex XML node for. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// GraphMLXmlDocument being populated. /// </param> /// /// <param name="oTagDictionary"> /// The key is the tag name and the value is the corresponding GraphML XML /// node that represents the tag. /// </param> //************************************************************************* protected void AppendVertexXmlNode( String sTag, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, XmlNode> oTagDictionary ) { Debug.Assert( !String.IsNullOrEmpty(sTag) ); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oTagDictionary != null); if ( !oTagDictionary.ContainsKey(sTag) ) { XmlNode oVertexXmlNode = oGraphMLXmlDocument.AppendVertexXmlNode( sTag); oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode, LabelID, sTag); oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode, MenuTextID, "Open Flickr Page for This Tag"); oGraphMLXmlDocument.AppendGraphMLAttributeValue( oVertexXmlNode, MenuActionID, String.Format( "http://www.flickr.com/photos/tags/{0}/" , UrlUtil.EncodeUrlParameter(sTag) ) ); oTagDictionary.Add(sTag, oVertexXmlNode); } }
//************************************************************************* // Method: TryAppendVertexXmlNode() // /// <summary> /// Appends a vertex XML node to the GraphML document for a user if such a /// node doesn't already exist. /// </summary> /// /// <param name="sUserName"> /// User name to add a vertex XML node for. /// </param> /// /// <param name="oEntryXmlNode"> /// The "entry" XML node returned by YouTube, or null if an entry node /// isn't available. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// GraphMLXmlDocument being populated. /// </param> /// /// <param name="oUserNameDictionary"> /// The key is the user name and the value is the corresponding GraphML XML /// node that represents the user. /// </param> /// /// <returns> /// true if a vertex XML node was added, false if a vertex XML node already /// exists. /// </returns> //************************************************************************* protected Boolean TryAppendVertexXmlNode( String sUserName, XmlNode oEntryXmlNode, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, XmlNode> oUserNameDictionary ) { Debug.Assert( !String.IsNullOrEmpty(sUserName) ); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserNameDictionary != null); XmlNode oVertexXmlNode; if ( oUserNameDictionary.TryGetValue(sUserName, out oVertexXmlNode) ) { return (false); } oVertexXmlNode = oGraphMLXmlDocument.AppendVertexXmlNode(sUserName); oUserNameDictionary.Add(sUserName, oVertexXmlNode); oGraphMLXmlDocument.AppendGraphMLAttributeValue(oVertexXmlNode, MenuTextID, "Open YouTube Page for This Person"); oGraphMLXmlDocument.AppendGraphMLAttributeValue( oVertexXmlNode, MenuActionID, String.Format(WebPageUrlPattern, sUserName) ); return (true); }
//************************************************************************* // Method: SaveGraphCore() // /// <summary> /// Saves graph data to a stream. /// </summary> /// /// <param name="graph"> /// Graph to save. /// </param> /// /// <param name="stream"> /// Stream to save the graph data to. /// </param> /// /// <remarks> /// This method saves <paramref name="graph" /> to <paramref /// name="stream" />. It does not close <paramref name="stream" />. /// /// <para> /// The arguments have already been checked for validity. /// </para> /// /// </remarks> //************************************************************************* protected override void SaveGraphCore( IGraph graph, Stream stream ) { Debug.Assert(graph != null); Debug.Assert(stream != null); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = new GraphMLXmlDocument( graph.Directedness == GraphDirectedness.Directed); String [] asEdgeAttributeNames = ( String[] )graph.GetRequiredValue( ReservedMetadataKeys.AllEdgeMetadataKeys, typeof( String[] ) ); String [] asVertexAttributeNames = ( String[] )graph.GetRequiredValue( ReservedMetadataKeys.AllVertexMetadataKeys, typeof( String[] ) ); // Define the Graph-ML 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 Graph-ML 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 Graph-ML 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); }
//************************************************************************* // 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); }
//************************************************************************* // Method: TryAppendVertexXmlNode() // /// <summary> /// Appends a vertex XML node to the GraphML document for a user if such a /// node doesn't already exist. /// </summary> /// /// <param name="sUserID"> /// User ID to add a vertex XML node for. /// </param> /// /// <param name="sScreenName"> /// Screen name to add a vertex XML node for. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// GraphMLXmlDocument being populated. /// </param> /// /// <param name="oUserIDDictionary"> /// The key is the user ID and the value is the corresponding GraphML XML /// node that represents the user. /// </param> /// /// <returns> /// true if a vertex XML node was added, false if a vertex XML node already /// exists. /// </returns> //************************************************************************* protected Boolean TryAppendVertexXmlNode( String sUserID, String sScreenName, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, XmlNode> oUserIDDictionary ) { Debug.Assert( !String.IsNullOrEmpty(sUserID) ); Debug.Assert( !String.IsNullOrEmpty(sScreenName) ); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserIDDictionary != null); XmlNode oVertexXmlNode; if ( oUserIDDictionary.TryGetValue(sUserID, out oVertexXmlNode) ) { return (false); } oVertexXmlNode = oGraphMLXmlDocument.AppendVertexXmlNode(sScreenName); oUserIDDictionary.Add(sUserID, oVertexXmlNode); return (true); }