Ejemplo n.º 1
0
        public void TestLanguages()
        {
            // GetPublicationsFromInput1XLS_Using_MockNCBI reads four people from
            // Input1.xls and writes their publications to the datbase using
            // MockNCBI. MockNCBI gets its test data from TestHarvester\*.dat.

            // There are 22 English publications that belong to the four people
            string[] Languages            = { "eng" };
            int      ExpectedPublications = 22;

            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, Languages, ExpectedPublications);

            // There's one Russian publication
            Languages            = new string[] { "rus" };
            ExpectedPublications = 1;
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, Languages, ExpectedPublications);

            // There's one Spanish publication
            Languages            = new string[] { "spa" };
            ExpectedPublications = 1;
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, Languages, ExpectedPublications);

            // There's one Russian and one Spanish publication -- two total
            Languages            = new string[] { "spa", "rus" };
            ExpectedPublications = 2;
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, Languages, ExpectedPublications);

            // There are no French or Portugese publications
            Languages            = new string[] { "fre", "por" };
            ExpectedPublications = 0;
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, Languages, ExpectedPublications);

            // There are 22 English and one Russian publication
            Languages            = new string[] { "eng", "rus" };
            ExpectedPublications = 23;
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, Languages, ExpectedPublications);


            Languages            = null;
            ExpectedPublications = 24;
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, Languages, ExpectedPublications);
        }
Ejemplo n.º 2
0
        public void TestGrantsReport()
        {
            // Set up the database with test publications (and don't forget to add the
            // publication types!)
            DB = new Database("Publication Harvester Unit Test");
            Harvester harvester = new Harvester(DB);

            harvester.CreateTables();
            PublicationTypes PubTypes = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );

            PubTypes.WriteToDB(DB);
            reports = new Reports(DB, AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestReports\\pubmed_jifs.xls");
            Assert.IsTrue(reports.Weights.Count == 10);
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);

            // Write the grants report
            StreamWriter writer = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\GrantsReport.csv");

            reports.GrantsReport(writer);
            writer.Close();

            // Verify that the grants were written properly

            // Read the rows back from the file
            string ConnectionString =
                "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq="
                + AppDomain.CurrentDomain.BaseDirectory + ";";
            OdbcConnection  Connection  = new OdbcConnection(ConnectionString);
            OdbcDataAdapter DataAdapter = new OdbcDataAdapter
                                              ("SELECT * FROM [GrantsReport.csv]", Connection);
            DataTable Results = new DataTable();
            int       Rows    = DataAdapter.Fill(Results);

            Connection.Close();

            int numChecked = 0;

            // Check a few selected results
            foreach (DataRow Row in Results.Rows)
            {
                int    Year    = Convert.ToInt32(Row[0]);
                int    PMID    = Convert.ToInt32(Row[1]);
                string GrantID = Row[2].ToString();

                switch (PMID)
                {
                case 3086749:     // Guillemin
                    numChecked++;
                    Assert.IsTrue((Year == 1986) && (
                                      (GrantID == "AM-18811/AM/NIADDK") ||
                                      (GrantID == "HD-09690/HD/NICHD") ||
                                      (GrantID == "MH-00663/MH/NIMH") ||
                                      (GrantID == "AG 03106/AG/NIA") ||
                                      (GrantID == "DK-26741/DK/NIDDK")));
                    break;

                case 9049886:     // Van Eys
                    numChecked++;
                    Assert.IsTrue((Year == 1997) && (GrantID == "RO1-CA33097/CA/NCI"));
                    break;
                }
            }
            Assert.IsTrue(numChecked == 6);

            File.Delete(AppDomain.CurrentDomain.BaseDirectory + "\\GrantsReport.csv");
        }
Ejemplo n.º 3
0
        public void TestMeSHHeadingReport()
        {
            // Set up the database with test publications (and don't forget to add the
            // publication types!)
            DB = new Database("Publication Harvester Unit Test");
            Harvester harvester = new Harvester(DB);

            harvester.CreateTables();
            PublicationTypes PubTypes = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );

            PubTypes.WriteToDB(DB);
            reports = new Reports(DB, AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestReports\\pubmed_jifs.xls");
            Assert.IsTrue(reports.Weights.Count == 10);
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);

            // Write the MeSH Heading report
            StreamWriter writer = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\MeSHHeadingReport.csv");

            Reports.ReportStatus StatusCallback = delegate(int number, int total, Person person, bool ProgressBarOnly)
            {
                //
            };
            Reports.ReportMessage MessageCallback = delegate(string Message)
            {
                //
            };
            reports.MeSHHeadingReport(writer, StatusCallback, MessageCallback);
            writer.Close();

            // Verify that the MeSH headings were written properly

            // Read the rows back from the file
            string ConnectionString =
                "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq="
                + AppDomain.CurrentDomain.BaseDirectory + ";";
            OdbcConnection  Connection  = new OdbcConnection(ConnectionString);
            OdbcDataAdapter DataAdapter = new OdbcDataAdapter
                                              ("SELECT * FROM [MeSHHeadingReport.csv]", Connection);
            DataTable Results = new DataTable();
            int       Rows    = DataAdapter.Fill(Results);

            Connection.Close();

            int numChecked = 0;

            // Check a few selected results
            foreach (DataRow Row in Results.Rows)
            {
                string Setnb   = Row[0].ToString();
                int    Year    = Convert.ToInt32(Row[1]);
                string Heading = Row[2].ToString();
                int    Count   = Convert.ToInt32(Row[3]);

                switch (Setnb)
                {
                case "A6009400":     // Van Eys
                    if ((Year == 1998) && (Heading == "Humans"))
                    {
                        Assert.IsTrue(Count == 2);
                        numChecked++;
                    }
                    if ((Year == 1998) && (Heading == "Child"))
                    {
                        Assert.IsTrue(Count == 1);
                        numChecked++;
                    }
                    if ((Year == 2001) && (Heading == "Humans"))
                    {
                        Assert.IsTrue(Count == 1);
                        numChecked++;
                    }
                    break;

                case "A5702471":     // Guillemin
                    if ((Year == 2005) && (Heading == "Hypothalamic Hormones/*physiology"))
                    {
                        Assert.IsTrue(Count == 1);
                        numChecked++;
                    }
                    break;
                }
            }
            Assert.IsTrue(numChecked == 4);

            File.Delete(AppDomain.CurrentDomain.BaseDirectory + "\\MeSHHeadingReport.csv");
        }
Ejemplo n.º 4
0
        public void TestPeopleReportRows()
        {
            // Set up the database with test publications (and don't forget to add the
            // publication types!)
            DB = new Database("Publication Harvester Unit Test");
            Harvester harvester = new Harvester(DB);

            harvester.CreateTables();
            PublicationTypes PubTypes = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );

            PubTypes.WriteToDB(DB);
            reports = new Reports(DB, AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestReports\\pubmed_jifs.xls");
            Assert.IsTrue(reports.Weights.Count == 10);
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);
            people = new People(DB);


            foreach (Person person in people.PersonList)
            {
                Publications pubs = new Publications(DB, person, false);
                switch (person.Setnb)
                {
                case "A6009400":
                    // Van Eys has two publications in 1998, both have zero weight
                    DataRow Row = WriteAndReadBackCSVRow(reports.ReportRow(person, pubs, 1998));

                    Assert.IsTrue(Row.ItemArray.Length == 74);
                    Assert.IsTrue(Row.ItemArray[0].ToString() == "A6009400");
                    Assert.IsTrue(Row.ItemArray[1].ToString() == "1998");

                    // Verify that all values are zero, except for pubcount (#3),
                    // pubcount_pos1 (#5), 123pubcount (#15), 123pubcount_pos1 (#17),
                    // 3pubcount (#51), 3pubcount_pos1 (#53)
                    for (int i = 2; i <= 73; i++)
                    {
                        if ((i == 2) || (i == 4) || (i == 14) || (i == 16) ||
                            (i == 50) || (i == 52))
                        {
                            Assert.IsTrue(Row.ItemArray[i].ToString() == "2", "Failed at i == " + i.ToString());
                        }
                        else
                        {
                            Assert.IsTrue(Row.ItemArray[i].ToString() == "0", "Failed at i == " + i.ToString());
                        }
                    }
                    break;

                case "A5401532":
                    // Tobian has two publications in 1997 of type 3 with a
                    // combined weight of 4.602
                    Row = WriteAndReadBackCSVRow(reports.ReportRow(person, pubs, 1997));

                    Assert.IsTrue(Row.ItemArray.Length == 74);
                    Assert.IsTrue(Row.ItemArray[0].ToString() == "A5401532");
                    Assert.IsTrue(Row.ItemArray[1].ToString() == "1997");

                    // Verify that all values are zero, except for pubcount (#3),
                    // pubcount_pos1 (#5), 123pubcount (#15), 123pubcount_pos1 (#17),
                    // 3pubcount (#51), 3pubcount_pos1 (#53), which should be 2
                    //
                    // and wghtd_pubcount (#4), wghtd_pubcount_pos1 (#6),
                    // wghtd_123pubcount (#16), wghtd_123pubcount_pos1 (#18),
                    // wghtd_3pubcount (#52), wghtd_3pubcount_pos1 (#54),
                    // which should be 4.602
                    for (int i = 2; i <= 73; i++)
                    {
                        if ((i == 2) || (i == 4) || (i == 14) || (i == 16) ||
                            (i == 50) || (i == 52))
                        {
                            Assert.IsTrue(Row.ItemArray[i].ToString() == "2", "Failed at i == " + i.ToString());
                        }
                        else if ((i == 3) || (i == 5) || (i == 15) || (i == 17) ||
                                 (i == 51) || (i == 53))
                        {
                            Assert.IsTrue(Row.ItemArray[i].ToString() == "4.602", "Failed at i == " + i.ToString());
                        }
                        else
                        {
                            Assert.IsTrue(Row.ItemArray[i].ToString() == "0", "Failed at i == " + i.ToString());
                        }
                    }
                    break;
                }
            }
        }
Ejemplo n.º 5
0
        public void TestSkipSetnbs()
        {
            // Set up the database with test publications (and don't forget to add the
            // publication types!)
            DB = new Database("Publication Harvester Unit Test");
            Harvester harvester = new Harvester(DB);

            harvester.CreateTables();
            PublicationTypes PubTypes = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );

            PubTypes.WriteToDB(DB);
            reports = new Reports(DB, AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestReports\\pubmed_jifs.xls");
            Assert.IsTrue(reports.Weights.Count == 10);
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);
            people = new People(DB);


            Reports.ReportStatus StatusCallback = delegate(int number, int total, Person person, bool ProgressBarOnly)
            {
                //
            };
            Reports.ReportMessage MessageCallback = delegate(string Message)
            {
                //
            };

            // Set up the Setnbs to skip
            ArrayList SetnbsToSkip = new ArrayList();

            SetnbsToSkip.Add("A5401532");
            SetnbsToSkip.Add("A6009400");

            // Verify that the people report skips the setnbs
            StreamWriter writer = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\TestSkipSetnbs.csv");

            reports.PeopleReport(SetnbsToSkip, writer, StatusCallback, MessageCallback);
            writer.Close();
            StreamReader reader = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "\\TestSkipSetnbs.csv");
            string       Line   = reader.ReadLine(); // skip the header row

            while ((Line = reader.ReadLine()) != null)
            {
                Assert.IsFalse(Line.StartsWith("A5401532"));
                Assert.IsFalse(Line.StartsWith("A6009400"));
            }
            reader.Close();

            // Verify that the people report skips the setnbs
            writer = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\TestSkipSetnbs.csv", false);
            reports.PubsReport(SetnbsToSkip, writer, StatusCallback, MessageCallback);
            writer.Close();
            reader = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "\\TestSkipSetnbs.csv");
            Line   = reader.ReadLine(); // skip the header row
            while ((Line = reader.ReadLine()) != null)
            {
                Assert.IsFalse(Line.StartsWith("A5401532"));
                Assert.IsFalse(Line.StartsWith("A6009400"));
            }
            reader.Close();

            File.Delete(AppDomain.CurrentDomain.BaseDirectory + "\\TestSkipSetnbs.csv");
        }
Ejemplo n.º 6
0
        public void TestEntireReport()
        {
            string Setnb = "";

            // Set up the database with test publications (and don't forget to add the
            // publication types!)
            DB = new Database("Publication Harvester Unit Test");
            Harvester harvester = new Harvester(DB);

            harvester.CreateTables();
            PublicationTypes PubTypes = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );

            PubTypes.WriteToDB(DB);
            reports = new Reports(DB, AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestReports\\pubmed_jifs.xls");
            Assert.IsTrue(reports.Weights.Count == 10);
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);
            people = new People(DB);


            // Write the report
            StreamWriter writer = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\TestEntireReport.csv");

            Reports.ReportStatus StatusCallback   = delegate(int number, int total, Person person, bool ProgressBarOnly) {
                //
            };
            Reports.ReportMessage MessageCallback = delegate(string Message)
            {
                //
            };
            reports.PeopleReport(null, writer, StatusCallback, MessageCallback);
            writer.Close();

            // Read the report into an array
            var lines = File.ReadAllLines($"{AppDomain.CurrentDomain.BaseDirectory}\\TestEntireReport.csv")
                        .Select(line => line.Split(new char[] { ',' }));
            var header = lines.First();
            var data   = lines.Skip(1).ToList();

            Assert.AreEqual(85, data.Count);

            string ReportData(string setnb, string year, string column)
            {
                var index = Array.IndexOf(header, column);
                var row   = data.Where(line => line[0] == setnb && line[1] == year);

                Assert.AreEqual(1, row.Count(), $"Unable to find setnb={setnb} year={year} in TestEntireReport.csv");
                return(row.First()[index]);
            }

            var q = ReportData("A5401532", "1997", "wghtd_pubcount_pos1");

            // Read the report file that was generated by hand (TestEntireReport_Data.xls)
            // and check each value against the report that was generated by Reports()
            string[] Columns =
            {
                "setnb",                    "year",                   "pubcount",               "wghtd_pubcount",       "pubcount_pos1",
                "wghtd_pubcount_pos1",      "pubcount_posN",          "wghtd_pubcount_posN",
                "pubcount_posM",            "wghtd_pubcount_posM",    "pubcount_posNTL",
                "wghtd_pubcount_posNTL",    "pubcount_pos2",          "wghtd_pubcount_pos2",
                "123pubcount",              "wghtd_123pubcount",      "123pubcount_pos1",
                "wghtd_123pubcount_pos1",   "123pubcount_posN",       "wghtd_123pubcount_posN",
                "123pubcount_posM",         "wghtd_123pubcount_posM", "123pubcount_posNTL",
                "wghtd_123pubcount_posNTL", "123pubcount_pos2",       "wghtd_123pubcount_pos2",
                "1pubcount",                "wghtd_1pubcount",        "1pubcount_pos1",         "wghtd_1pubcount_pos1",
                "1pubcount_posN",           "wghtd_1pubcount_posN",   "1pubcount_posM",
                "wghtd_1pubcount_posM",     "1pubcount_posNTL",       "wghtd_1pubcount_posNTL",
                "1pubcount_pos2",           "wghtd_1pubcount_pos2",   "2pubcount",              "wghtd_2pubcount",
                "2pubcount_pos1",           "wghtd_2pubcount_pos1",   "2pubcount_posN",
                "wghtd_2pubcount_posN",     "2pubcount_posM",         "wghtd_2pubcount_posM",
                "2pubcount_posNTL",         "wghtd_2pubcount_posNTL", "2pubcount_pos2",
                "wghtd_2pubcount_pos2",     "3pubcount",              "wghtd_3pubcount",        "3pubcount_pos1",
                "wghtd_3pubcount_pos1",     "3pubcount_posN",         //"wghtd_3pubcount_posN",
                "3pubcount_posM",           "wghtd_3pubcount_posM",   "3pubcount_posNTL",
                "wghtd_3pubcount_posNTL",   "3pubcount_pos2",         "wghtd_3pubcount_pos2",
                "4pubcount",                "wghtd_4pubcount",        "4pubcount_pos1",         "wghtd_4pubcount_pos1",
                "4pubcount_posN",           "wghtd_4pubcount_posN",   "4pubcount_posM",
                "wghtd_4pubcount_posM",     "4pubcount_posNTL",       "wghtd_4pubcount_posNTL",
                "4pubcount_pos2",           "wghtd_4pubcount_pos2"
            };

            DataTable HandGeneratedData = NpoiHelper.ReadExcelFileToDataTable(AppDomain.CurrentDomain.BaseDirectory +
                                                                              "\\Unit Tests\\TestReports", "TestEntireReport_Data.xls");

            Assert.AreEqual(HandGeneratedData.Rows.Count, 85);

            var valuesChecked = 0;

            for (int RowNum = 0; RowNum < HandGeneratedData.Rows.Count; RowNum++)
            {
                // Find the rows in the hand-generated data and the report
                DataRow HandGeneratedRow = HandGeneratedData.Rows[RowNum];
                Setnb = HandGeneratedRow[0].ToString();
                int Year = Convert.ToInt32(HandGeneratedRow[1]);

                for (int i = 2; i < Columns.Length; i++)
                {
                    valuesChecked++;
                    String columnName    = Columns[i];
                    var    actualValue   = ReportData(Setnb, Year.ToString(), columnName);
                    string expectedValue = HandGeneratedRow[columnName].ToString();
                    Assert.AreEqual(expectedValue, actualValue, Setnb + "/" + Year.ToString() + "/" + columnName + " -- hand generated has " + expectedValue + ", report has" + actualValue);
                }
            }

            Assert.AreEqual((HandGeneratedData.Rows.Count) * (Columns.Length - 2), valuesChecked);

            // Use BackupReportAndGetSetnbs to back up the report -- check that it
            // returns the correct list of Setnbs and removes the last one from
            // the file. The last Setnb should still be in Setnb.
            ArrayList Setnbs = Reports.BackupReportAndGetSetnbs(AppDomain.CurrentDomain.BaseDirectory + "\\TestEntireReport.csv");
            // Read the backup file that was created, make sure that the last setnb in the
            // file isn't contained and the others are
            StreamReader reader = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "\\TestEntireReport.csv.bak");
            string       Line   = reader.ReadLine();   //skip the header row

            while ((Line = reader.ReadLine()) != null) // Find the last setnb in the original file
            {
                Setnb = Line.Substring(0, 8);
            }
            string RemovedSetnb = Setnb;

            Assert.IsFalse(Setnbs.Contains(RemovedSetnb));
            reader.Close();

            // Verify that the new file contains only the other setnbs
            Assert.IsTrue(Setnbs.Count == 3);
            Assert.IsFalse(Setnbs.Contains(RemovedSetnb));
            reader = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "\\TestEntireReport.csv");
            Line   = reader.ReadLine(); //skip the header row
            while ((Line = reader.ReadLine()) != null)
            {
                Setnb = Line.Substring(0, 8);
                Assert.IsTrue(Setnbs.Contains(Setnb));
                Assert.IsFalse(Setnb == RemovedSetnb);
            }
            reader.Close();

            // Delete the temporary files
            File.Delete(AppDomain.CurrentDomain.BaseDirectory + "\\TestEntireReport.csv");
            File.Delete(AppDomain.CurrentDomain.BaseDirectory + "\\TestEntireReport.csv.bak");
        }
Ejemplo n.º 7
0
        public void TestPubsReportRow()
        {
            // Set up the database with test publications (and don't forget to add the
            // publication types!)
            DB = new Database("Publication Harvester Unit Test");
            Harvester harvester = new Harvester(DB);

            harvester.CreateTables();
            PublicationTypes PubTypes = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );

            PubTypes.WriteToDB(DB);
            reports = new Reports(DB, AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestReports\\pubmed_jifs.xls");
            Assert.IsTrue(reports.Weights.Count == 10);
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);
            people = new People(DB);


            foreach (Person person in people.PersonList)
            {
                Publications pubs = new Publications(DB, person, false);

                if (pubs.PublicationList != null)
                {
                    foreach (Publication pub in pubs.PublicationList)
                    {
                        DataRow Row = WriteAndReadBackCSVRow(reports.PubsReportRow(person, pub));

                        switch (pub.PMID)
                        {
                        case 15249795:
                            // 0. setnb
                            Assert.IsTrue(Row.ItemArray[0].ToString() == "A5401532");

                            // 1. pmid
                            Assert.IsTrue(Row.ItemArray[1].ToString() == "15249795");

                            // 2. journal_name
                            Assert.IsTrue(Row.ItemArray[2].ToString() == "J Clin Hypertens (Greenwich)");

                            // 3. year
                            Assert.IsTrue(Row.ItemArray[3].ToString() == "2004");

                            // 4. Month
                            Assert.IsTrue(Row.ItemArray[4].ToString() == "Jul");

                            // 5. day
                            Assert.IsTrue(Row.ItemArray[5].ToString() == "");

                            // 6. title
                            Assert.IsTrue(Row.ItemArray[6].ToString() == "Interview with Louis Tobian, MD. Interview by Marvin Moser.");

                            // 7. Volume
                            Assert.IsTrue(Row.ItemArray[7].ToString() == "6");

                            // 8. issue
                            Assert.IsTrue(Row.ItemArray[8].ToString() == "7");

                            // 9. position
                            Assert.IsTrue(Row.ItemArray[9].ToString() == "1");

                            // 10. nbauthors
                            Assert.IsTrue(Row.ItemArray[10].ToString() == "1");

                            // 11. Bin
                            Assert.IsTrue(Row.ItemArray[11].ToString() == "0");

                            // 12. Pages
                            Assert.IsTrue(Row.ItemArray[12].ToString() == "391-2");

                            // 13. Publication_type
                            Assert.IsTrue(Row.ItemArray[13].ToString() == "Historical Article");


                            break;
                        }
                    }
                }
            }
        }
Ejemplo n.º 8
0
        public void TestTwoPeopleWithSameNames()
        {
            Database DB = new Database("Publication Harvester Unit Test");

            // Set up the database
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);


            // Add two people to the database with the same names and search criteria
            // (where the search should make MockNCBI use OtherPeople.dat)
            string[] names = new string[2];
            names[0] = "Guy JF";
            names[1] = "Guy J";
            Person Joe = new Person("A1234567", "JOE", "FIRST", "GUY",
                                    false, names, "Special query for OtherPeople.dat");

            Joe.WriteToDB(DB);

            Person Jane = new Person("Z7654321", "JANE", "FIFTH", "GUY",
                                     false, names, "Special query for OtherPeople.dat");

            Jane.WriteToDB(DB);


            // Also add Jim, but give him an error so we can make sure it's cleared
            Person Jim = new Person("Q2222222", "JIM", "FOURTEENTH", "GUY",
                                    false, names, "Special query for OtherPeople.dat");

            Jim.WriteToDB(DB);
            Jim.WriteErrorToDB(DB, "This is an error message");


            PublicationTypes ptc = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );


            // Make an anonymous callback function that keeps track of the callback data
            int Callbacks = 0; // this will count all of the publications

            Harvester.GetPublicationsStatus StatusCallback = delegate(int number, int total, int averageTime)
            {
                Callbacks++;
            };

            // Make an anonymous callback function to do nothing for GetPublicationsMessage
            int MessageCallbacks = 0;

            Harvester.GetPublicationsMessage MessageCallback = delegate(string Message, bool StatusBarOnly)
            {
                // Only increment MessageCallbacks if the message contains Joe's Setnb
                // and the word "same"
                if ((Message.Contains("A1234567") || (Message.Contains("Q2222222")) &&
                     Message.Contains("same")))
                {
                    MessageCallbacks++;
                }
            };

            // Make an anonymous callback function to return false for CheckForInterrupt
            Harvester.CheckForInterrupt InterruptCallback = delegate()
            {
                return(false);
            };

            // More stuff for the harvester
            Harvester harvester = new Harvester(DB);
            MockNCBI  mockNCBI  = new MockNCBI("medline");
            double    AverageMilliseconds;


            // Harvest the people
            harvester.GetPublications(mockNCBI, ptc, Jane, StatusCallback, MessageCallback, InterruptCallback, out AverageMilliseconds);

            // Make sure the harvester got Jane's publications
            DataTable Results = DB.ExecuteQuery("SELECT PMID FROM PeoplePublications WHERE Setnb = 'Z7654321'");

            Assert.AreEqual(Results.Rows.Count, 3);
            foreach (DataRow Row in Results.Rows)
            {
                Assert.IsTrue(
                    (Row["PMID"].ToString() == "2417121") ||
                    (Row["PMID"].ToString() == "12679283") ||
                    (Row["PMID"].ToString() == "14653276"));
            }
            ArrayList Parameters = new ArrayList();

            Parameters.Add(Database.Parameter(Jane.Setnb));
            Results = DB.ExecuteQuery("SELECT Harvested, Error, ErrorMessage FROM People WHERE Setnb = ?", Parameters);
            Assert.AreEqual(Results.Rows[0]["Harvested"], true);
            Assert.AreEqual(Results.Rows[0]["Error"], DBNull.Value);
            Assert.AreEqual(Results.Rows[0]["ErrorMessage"].ToString(), "");


            // It should also get Joe's publications. It should call MessageCallback()
            // twice to let us know Joe'and Jim's s publications were found, and it
            // should add the appropriate rows to PeoplePublications.
            Assert.AreEqual(MessageCallbacks, 2);
            Results = DB.ExecuteQuery("SELECT PMID FROM PeoplePublications WHERE Setnb = 'A1234567'");
            Assert.AreEqual(Results.Rows.Count, 3);
            foreach (DataRow Row in Results.Rows)
            {
                Assert.IsTrue(
                    (Row["PMID"].ToString() == "2417121") ||
                    (Row["PMID"].ToString() == "12679283") ||
                    (Row["PMID"].ToString() == "14653276"));
            }
            Parameters = new ArrayList();
            Parameters.Add(Database.Parameter(Joe.Setnb));
            Results = DB.ExecuteQuery("SELECT " + Database.PEOPLE_COLUMNS + " FROM People WHERE Setnb = ?", Parameters);
            bool boolValue; // needed for GetBoolValue workaround for bit field bug in MySQL

            Assert.IsTrue(Database.GetBoolValue(Results.Rows[0]["Harvested"], out boolValue));
            Assert.IsTrue(boolValue);
            Assert.IsTrue(Database.GetBoolValue(Results.Rows[0]["Error"], out boolValue));
            Assert.IsFalse(boolValue);
            Assert.AreEqual(Results.Rows[0]["Error"], DBNull.Value);
            Assert.AreEqual(Results.Rows[0]["ErrorMessage"].ToString(), "");



            // It should also get Jim's publications -- and it should also clear his error.
            Assert.AreEqual(MessageCallbacks, 2);
            Results = DB.ExecuteQuery("SELECT PMID FROM PeoplePublications WHERE Setnb = 'A1234567'");
            Assert.AreEqual(Results.Rows.Count, 3);
            foreach (DataRow Row in Results.Rows)
            {
                Assert.IsTrue(
                    (Row["PMID"].ToString() == "2417121") ||
                    (Row["PMID"].ToString() == "12679283") ||
                    (Row["PMID"].ToString() == "14653276"));
            }
            Parameters = new ArrayList();
            Parameters.Add(Database.Parameter(Jim.Setnb));
            Results = DB.ExecuteQuery("SELECT " + Database.PEOPLE_COLUMNS + "FROM People WHERE Setnb = ?", Parameters);

            Assert.IsTrue(Database.GetBoolValue(Results.Rows[0]["Harvested"], out boolValue));
            Assert.AreEqual(boolValue, true);
            Assert.AreEqual(Results.Rows[0]["Error"], DBNull.Value);
            Assert.AreEqual(Results.Rows[0]["ErrorMessage"].ToString(), "");
        }
Ejemplo n.º 9
0
 public void TestNCBIError()
 {
     // Set up the database -- tell MockNCBI to throw an error
     // This function does all of the necessary testing.
     TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);
 }
Ejemplo n.º 10
0
        public void TestClearingDataAfterInterruption()
        {
            // Set up the database
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);

            Database  DB        = new Database("Publication Harvester Unit Test");
            Harvester harvester = new Harvester(DB);

            // Add a grant for publication 12462241, since it doesn't have one
            ArrayList Parameters = new ArrayList();

            Parameters.Add(Database.Parameter(12462241));
            Parameters.Add(Database.Parameter("Fake grant ID"));
            DB.ExecuteNonQuery("INSERT INTO PublicationGrants (PMID, GrantID) VALUES ( ? , ? )", Parameters);


            // Verify that InterruptedDataExists and UnharvestedPeopleExist both return false
            Assert.IsFalse(harvester.InterruptedDataExists());
            Assert.IsFalse(harvester.UnharvestedPeopleExist());

            // Verify that there are publications for Tobian (setnb A5401532)
            // (there should be 5 publications)

            Assert.IsTrue(DB.GetIntValue(
                              @"SELECT Count(*) 
                    FROM PeoplePublications
                   WHERE Setnb = 'A5401532'") == 5);
            int TotalPublicationsBeforeClear
                = DB.GetIntValue("SELECT Count(*) FROM PeoplePublications");

            // Verify that there are authors and MeSH headings for publication 12462241
            // (which belongs to Guillemin, and should have 82 authors and 9 headings)

            Assert.IsTrue(DB.GetIntValue(
                              @"SELECT Count(*) 
                    FROM PublicationMeSHHeadings
                   WHERE PMID = 12462241") == 9);
            int TotalHeadingsBeforeClear
                = DB.GetIntValue("SELECT Count(*) FROM PublicationMeSHHeadings");

            Assert.IsTrue(DB.GetIntValue(
                              @"SELECT Count(*) 
                    FROM PublicationAuthors
                   WHERE PMID = 12462241") == 82);
            int TotalAuthorsBeforeClear
                = DB.GetIntValue("SELECT Count(*) FROM PublicationAuthors");

            Assert.IsTrue(DB.GetIntValue(
                              @"SELECT Count(*) 
                    FROM PublicationGrants
                   WHERE PMID = 12462241") == 1);
            int TotalGrantsBeforeClear
                = DB.GetIntValue("SELECT Count(*) FROM PublicationGrants");

            // Set Tobian's Harvested to 0
            DB.ExecuteNonQuery("UPDATE People SET Harvested = 0 WHERE Setnb = 'A5401532'");

            // Remove publication 12462241
            DB.ExecuteNonQuery("DELETE FROM Publications WHERE PMID = 12462241");


            // Verify that InterruptedDataExists and UnharvestedPeopleExist both return true
            Assert.IsTrue(harvester.InterruptedDataExists());
            Assert.IsTrue(harvester.UnharvestedPeopleExist());

            // Execute ClearDataAfterInterruption
            harvester.ClearDataAfterInterruption();

            // Verify that InterruptedDataExists returns false again, now that
            // the intterrupted data has been cleared, but that there are still
            // unharvested people
            Assert.IsFalse(harvester.InterruptedDataExists());
            Assert.IsTrue(harvester.UnharvestedPeopleExist());

            // Verify that only Tobian's publications have been removed
            Assert.IsTrue(
                DB.GetIntValue("SELECT Count(*) FROM PeoplePublications")
                == TotalPublicationsBeforeClear - 5);

            // Verify that only publication 12462241's grants, headings and authors have been removed
            Assert.IsTrue(
                DB.GetIntValue("SELECT Count(*) FROM PublicationMeSHHeadings")
                == TotalHeadingsBeforeClear - 9);

            Assert.IsTrue(
                DB.GetIntValue("SELECT Count(*) FROM PublicationAuthors")
                == TotalAuthorsBeforeClear - 82);

            Assert.IsTrue(
                DB.GetIntValue("SELECT Count(*) FROM PublicationGrants")
                == TotalGrantsBeforeClear - 1);
        }
Ejemplo n.º 11
0
        public void GetPublications()
        {
            // Set up the database
            TestHarvester.GetPublicationsFromInput1XLS_Using_MockNCBI(false, new string[] { "eng" }, 22);

            Database         DB  = new Database("Publication Harvester Unit Test");
            PublicationTypes ptc = new PublicationTypes(
                AppDomain.CurrentDomain.BaseDirectory + "\\Unit Tests\\TestPublicationTypes",
                "PublicationTypes.csv"
                );

            // Verify the correct publications were written (including publication type and author position)
            People people = new People(DB);

            Assert.IsTrue(people.PersonList.Count == 4);
            int FoundPublications = 0;

            foreach (Person person in people.PersonList)
            {
                Publications pubs = new Publications(DB, person, false);
                switch (person.Setnb)
                {
                case "A6009400":     // Van Eys
                    Assert.IsTrue(pubs.PublicationList.Length == 8);
                    if (pubs.PublicationList != null)
                    {
                        foreach (Publication pub in pubs.PublicationList)
                        {
                            switch (pub.PMID)
                            {
                            case 9876482:
                                FoundPublications++;
                                Assert.IsTrue(pub.Title == "Benefits of nutritional intervention on nutritional status, quality of life and survival.");
                                Assert.IsTrue(pub.Pages == "66-8");
                                Assert.IsTrue(pub.Year == 1998);
                                Assert.IsTrue(pub.Month == null);
                                Assert.IsTrue(pub.Day == null);
                                Assert.IsTrue(pub.Journal == "Int J Cancer Suppl");
                                Assert.IsTrue(pub.Volume == "11");
                                Assert.IsTrue(pub.Issue == null);

                                Assert.IsTrue(pub.Authors.Length == 1);
                                Assert.IsTrue(pub.Authors[0] == "Van Eys J");

                                // Verify publication type
                                Assert.IsTrue(pub.PubType == "Journal Article");
                                Assert.IsTrue(ptc.GetCategoryNumber(pub.PubType) == 3);

                                // Verify MeSH headings
                                Assert.IsTrue(pub.MeSHHeadings.Count == 8);
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Child"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Nutrition Disorders/*complications/*therapy"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Survival Rate"));

                                // Verify position type
                                Harvester.AuthorPositions PositionType;
                                int AuthorPosition = Publications.GetAuthorPosition(DB, pub.PMID, person, out PositionType, "PeoplePublications");
                                Assert.IsTrue(AuthorPosition == 1);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.First);
                                AuthorPosition = person.GetAuthorPosition(DB, pub, out PositionType);
                                Assert.IsTrue(AuthorPosition == 1);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.First);
                                break;



                            case 8403744:
                                FoundPublications++;
                                Assert.IsTrue(pub.Title == "Early hospital discharge and the timing of newborn metabolic screening.");
                                Assert.IsTrue(pub.Pages == "463-6");
                                Assert.IsTrue(pub.Year == 1993);
                                Assert.IsTrue(pub.Month == "Aug");
                                Assert.IsTrue(pub.Day == null);
                                Assert.IsTrue(pub.Journal == "Clin Pediatr (Phila)");
                                Assert.IsTrue(pub.Volume == "32");
                                Assert.IsTrue(pub.Issue == "8");

                                Assert.IsTrue(pub.Authors.Length == 4);
                                Assert.IsTrue(pub.Authors[0] == "Coody D");
                                Assert.IsTrue(pub.Authors[1] == "Yetman RJ");
                                Assert.IsTrue(pub.Authors[2] == "Montgomery D");
                                Assert.IsTrue(pub.Authors[3] == "van Eys J");

                                // Verify publication type
                                Assert.IsTrue(pub.PubType == "Consensus Development Conference, NIH");
                                Assert.IsTrue(ptc.GetCategoryNumber(pub.PubType) == 1);

                                // Verify MeSH headings
                                Assert.IsTrue(pub.MeSHHeadings.Count == 15);
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Cesarean Section"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Hospitals, Private"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("*Insurance, Health"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("United States"));

                                // Verify position type
                                AuthorPosition = Publications.GetAuthorPosition(DB, pub.PMID, person, out PositionType, "PeoplePublications");
                                Assert.IsTrue(AuthorPosition == 4);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.Last);
                                AuthorPosition = person.GetAuthorPosition(DB, pub, out PositionType);
                                Assert.IsTrue(AuthorPosition == 4);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.Last);
                                break;
                            }
                        }
                    }
                    break;

                case "A5401532":     // Tobian
                    Assert.IsTrue(pubs.PublicationList.Length == 5);
                    if (pubs.PublicationList != null)
                    {
                        foreach (Publication pub in pubs.PublicationList)
                        {
                            switch (pub.PMID)
                            {
                            case 9931073:
                                FoundPublications++;
                                Assert.IsTrue(pub.Title == "Story of the birth of the journal called Hypertension.");
                                Assert.IsTrue(pub.Pages == "7");
                                Assert.IsTrue(pub.Year == 1999);
                                Assert.IsTrue(pub.Month == "Jan");
                                Assert.IsTrue(pub.Day == null);
                                Assert.IsTrue(pub.Volume == "33");
                                Assert.IsTrue(pub.Issue == "1");

                                Assert.IsTrue(pub.Authors.Length == 1);
                                Assert.IsTrue(pub.Authors[0] == "Tobian L");

                                // Verify publication type
                                Assert.IsTrue(pub.PubType == "Historical Article");
                                Assert.IsTrue(ptc.GetCategoryNumber(pub.PubType) == 0);

                                // Verify MeSH headings
                                Assert.IsTrue(pub.MeSHHeadings.Count == 5);
                                Assert.IsTrue(pub.MeSHHeadings.Contains("American Heart Association/*history"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("*Hypertension"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("United States"));

                                // Verify position type
                                Harvester.AuthorPositions PositionType;
                                int AuthorPosition = Publications.GetAuthorPosition(DB, pub.PMID, person, out PositionType, "PeoplePublications");
                                Assert.IsTrue(AuthorPosition == 1);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.First);
                                AuthorPosition = person.GetAuthorPosition(DB, pub, out PositionType);
                                Assert.IsTrue(AuthorPosition == 1);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.First);
                                break;
                            }
                        }
                    }
                    break;

                case "A5501586":     // Reemtsma
                    Assert.IsTrue(pubs.PublicationList.Length == 3);
                    if (pubs.PublicationList != null)
                    {
                        foreach (Publication pub in pubs.PublicationList)
                        {
                            switch (pub.PMID)
                            {
                            case 11528018:
                                FoundPublications++;
                                Assert.IsTrue(pub.Title == "Xenotransplantation: A Historical Perspective.");
                                Assert.IsTrue(pub.Pages == "9-12");
                                Assert.IsTrue(pub.Year == 1995);
                                Assert.IsTrue(pub.Month == null);
                                Assert.IsTrue(pub.Day == null);
                                Assert.IsTrue(pub.Volume == "37");
                                Assert.IsTrue(pub.Issue == "1");

                                Assert.IsTrue(pub.Authors.Length == 1);
                                Assert.IsTrue(pub.Authors[0] == "Reemtsma K");

                                // Verify publication type
                                Assert.IsTrue(pub.PubType == "JOURNAL ARTICLE");
                                Assert.IsTrue(ptc.GetCategoryNumber(pub.PubType) == 3);

                                // Verify MeSH headings
                                Assert.IsTrue(pub.MeSHHeadings == null);

                                // Verify position type
                                Harvester.AuthorPositions PositionType;
                                int AuthorPosition = Publications.GetAuthorPosition(DB, pub.PMID, person, out PositionType, "PeoplePublications");
                                Assert.IsTrue(AuthorPosition == 1);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.First);
                                AuthorPosition = person.GetAuthorPosition(DB, pub, out PositionType);
                                Assert.IsTrue(AuthorPosition == 1);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.First);
                                break;
                            }
                        }
                    }
                    break;



                case "A5702471":     // Guillemin
                    Assert.IsTrue(pubs.PublicationList.Length == 6);
                    if (pubs.PublicationList != null)
                    {
                        foreach (Publication pub in pubs.PublicationList)
                        {
                            switch (pub.PMID)
                            {
                            case 15642779:
                                // For this publication, we're just concerned that
                                // the publication type is "Review" -- even though
                                // it's the second publication type in the citation,
                                // it's flagged as an "override first pubtype"
                                // in PublicationTypes.csv
                                Assert.IsTrue(pub.PubType == "Review");
                                break;


                            // NOTE: The title has a quote (laureates') that gets stripped off
                            case 12462241:
                                FoundPublications++;
                                Assert.IsTrue(pub.Title == "Nobel laureates letter to President Bush.");
                                Assert.IsTrue(pub.Pages == "A02");
                                Assert.IsTrue(pub.Year == 2001);
                                Assert.IsTrue(pub.Month == "Feb");
                                Assert.IsTrue(pub.Day == "22");
                                Assert.IsTrue(pub.Journal == "Washington Post");
                                Assert.IsTrue(pub.Volume == null);
                                Assert.IsTrue(pub.Issue == null);

                                Assert.IsTrue(pub.Authors.Length == 82);
                                Assert.IsTrue(pub.Authors[0] == "Arrow KJ");
                                Assert.IsTrue(pub.Authors[26] == "Guillemin R");
                                Assert.IsTrue(pub.Authors[81] == "Wilson RW");

                                // Verify publication type
                                Assert.IsTrue(pub.PubType == "Newspaper Article");
                                Assert.IsTrue(ptc.GetCategoryNumber(pub.PubType) == 0);

                                // Verify MeSH headings
                                Assert.IsTrue(pub.MeSHHeadings.Count == 9);
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Embryo Disposition"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("National Institutes of Health (U.S.)"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("United States"));

                                // Verify position type
                                Harvester.AuthorPositions PositionType;
                                int AuthorPosition = Publications.GetAuthorPosition(DB, pub.PMID, person, out PositionType, "PeoplePublications");
                                Assert.IsTrue(AuthorPosition == 27);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.Middle);
                                AuthorPosition = person.GetAuthorPosition(DB, pub, out PositionType);
                                Assert.IsTrue(AuthorPosition == 27);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.Middle);
                                break;


                            case 3086749:
                                // This publication was altered to contain six GrantIDs in order to
                                // test the GrantID column length in the database
                                FoundPublications++;
                                Assert.IsTrue(pub.Title == "Pituitary FSH is released by a heterodimer of the beta-subunits from the two forms of inhibin.");
                                Assert.IsTrue(pub.Pages == "779-82");
                                Assert.IsTrue(pub.Year == 1986);
                                Assert.IsTrue(pub.Month == "Jun");
                                Assert.IsTrue(pub.Day == "19-25");
                                Assert.IsTrue(pub.Journal == "Nature");
                                Assert.IsTrue(pub.Volume == "321");
                                Assert.IsTrue(pub.Issue == "6072");

                                Assert.IsTrue(pub.Authors.Length == 7);
                                Assert.IsTrue(pub.Authors[0] == "Ling N");
                                Assert.IsTrue(pub.Authors[4] == "Esch F");
                                Assert.IsTrue(pub.Authors[6] == "Guillemin R");

                                // Verify publication type
                                Assert.IsTrue(pub.PubType == "Journal Article");
                                Assert.IsTrue(ptc.GetCategoryNumber(pub.PubType) == 3);

                                // Verify MeSH headings
                                Assert.IsTrue(pub.MeSHHeadings.Count == 14);
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Amino Acid Sequence"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Follicle Stimulating Hormone/*secretion"));
                                Assert.IsTrue(pub.MeSHHeadings.Contains("Swine"));

                                // Verify position type
                                AuthorPosition = Publications.GetAuthorPosition(DB, pub.PMID, person, out PositionType, "PeoplePublications");
                                Assert.IsTrue(AuthorPosition == 7);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.Last);
                                AuthorPosition = person.GetAuthorPosition(DB, pub, out PositionType);
                                Assert.IsTrue(AuthorPosition == 7);
                                Assert.IsTrue(PositionType == Harvester.AuthorPositions.Last);
                                break;
                            }
                        }
                    }
                    break;
                }
            }
            Assert.IsTrue(FoundPublications == 6);

            // Verify that People.Harvested has been updated for each person
            DataTable Results = DB.ExecuteQuery("SELECT Setnb, Harvested FROM People");

            Assert.IsTrue(Results.Rows.Count == 4);
            foreach (DataRow Row in Results.Rows)
            {
                Assert.IsTrue((bool)Row["Harvested"] == true);
            }
        }