Example #1
0
        GetUserNetworkRecursive
        (
            String sUserID,
            String sScreenName,
            WhatToInclude eWhatToInclude,
            Boolean bIncludeContactsThisCall,
            NetworkLevel eNetworkLevel,
            Int32 iMaximumPerRequest,
            String sApiKey,
            Int32 iRecursionLevel,
            GraphMLXmlDocument oGraphMLXmlDocument,
            Dictionary <String, XmlNode> oUserIDDictionary,
            RequestStatistics oRequestStatistics
        )
        {
            Debug.Assert(!String.IsNullOrEmpty(sUserID));
            Debug.Assert(!String.IsNullOrEmpty(sScreenName));

            Debug.Assert(eNetworkLevel == NetworkLevel.One ||
                         eNetworkLevel == NetworkLevel.OnePointFive ||
                         eNetworkLevel == NetworkLevel.Two);

            Debug.Assert(iMaximumPerRequest > 0);
            Debug.Assert(!String.IsNullOrEmpty(sApiKey));
            Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2);
            Debug.Assert(oGraphMLXmlDocument != null);
            Debug.Assert(oUserIDDictionary != 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);

            Boolean bNeedToAppendVertices = GetNeedToAppendVertices(eNetworkLevel,
                                                                    iRecursionLevel);

            List <String> oUserIDsToRecurse = new List <String>();

            ReportProgressForContactsOrCommenters(sScreenName,
                                                  bIncludeContactsThisCall);

            Boolean bThisUserAppended = false;

            foreach (XmlNode oChildXmlNode in GetContactsOrCommentersEnumerator(
                         sUserID, bIncludeContactsThisCall, iMaximumPerRequest,
                         oGraphMLXmlDocument, sApiKey, oRequestStatistics))
            {
                String sOtherScreenName, sOtherUserID;

                if (
                    !XmlUtil2.TrySelectSingleNodeAsString(oChildXmlNode,
                                                          bIncludeContactsThisCall ? "@username" : "@authorname",
                                                          null, out sOtherScreenName)
                    ||
                    !XmlUtil2.TrySelectSingleNodeAsString(oChildXmlNode,
                                                          bIncludeContactsThisCall ? "@nsid" : "@author",
                                                          null, out sOtherUserID)
                    )
                {
                    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(sUserID, sScreenName,
                                           oGraphMLXmlDocument, oUserIDDictionary);

                    bThisUserAppended = true;
                }

                if (bNeedToAppendVertices)
                {
                    if (
                        TryAppendVertexXmlNode(sOtherUserID, sOtherScreenName,
                                               oGraphMLXmlDocument, oUserIDDictionary)
                        &&
                        bNeedToRecurse
                        )
                    {
                        oUserIDsToRecurse.Add(sOtherUserID);
                    }
                }

                if (bNeedToAppendVertices ||
                    oUserIDDictionary.ContainsKey(sOtherUserID))
                {
                    // Append an edge node and optional attributes.

                    XmlNode oEdgeXmlNode;

                    if (bIncludeContactsThisCall)
                    {
                        oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument,
                                                         sScreenName, sOtherScreenName, "Contact");
                    }
                    else
                    {
                        // (Note the swapping of screen names in the commenter
                        // case.)

                        oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument,
                                                         sOtherScreenName, sScreenName, "Commenter");

                        UInt32 uCommentDateUtc;

                        if (XmlUtil2.TrySelectSingleNodeAsUInt32(oChildXmlNode,
                                                                 "@datecreate", null, out uCommentDateUtc))
                        {
                            DateTime oCommentDateUtc =
                                DateTimeUtil2.UnixTimestampToDateTimeUtc(
                                    uCommentDateUtc);

                            oGraphMLXmlDocument.AppendGraphMLAttributeValue(
                                oEdgeXmlNode, CommentDateUtcID,

                                ExcelDateTimeUtil.DateTimeToStringLocale1033(
                                    oCommentDateUtc, ExcelColumnFormat.DateAndTime)
                                );
                        }

                        AppendStringGraphMLAttributeValue(oChildXmlNode,
                                                          "@permalink", null, oGraphMLXmlDocument, oEdgeXmlNode,
                                                          CommentUrlID);
                    }
                }
            }

            if (bNeedToRecurse)
            {
                foreach (String sUserIDToRecurse in oUserIDsToRecurse)
                {
                    XmlNode oVertexXmlNode = oUserIDDictionary[sUserIDToRecurse];

                    String sScreenNameToRecurse = GetScreenNameFromVertexXmlNode(
                        oVertexXmlNode);

                    GetUserNetworkRecursive(sUserIDToRecurse, sScreenNameToRecurse,
                                            eWhatToInclude, bIncludeContactsThisCall, eNetworkLevel,
                                            iMaximumPerRequest, sApiKey, 2, oGraphMLXmlDocument,
                                            oUserIDDictionary, oRequestStatistics);
                }
            }
        }