Ejemplo n.º 1
0
        /// <summary> Constructor for a new instance of the User_Tags_MySobekViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public User_Usage_Stats_MySobekViewer(User_Object User, SobekCM_Navigation_Object Current_Mode, Statistics_Dates Stats_Date_Range, Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("User_Usage_Stats_MySobekViewer.Constructor", String.Empty);

            currentMode = Current_Mode;
            statsDates  = Stats_Date_Range;
        }
        /// <summary> Refresh the statistics date range by pulling the data back from the database </summary>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public static bool RefreshStatsDateRange()
        {
            try
            {
                lock (statsDatesLock)
                {
                    if (statsDates == null)
                    {
                        statsDates = new Statistics_Dates();
                    }

                    // Get the data from the database
                    Engine_Database.Populate_Statistics_Dates(statsDates, null);
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
Ejemplo n.º 3
0
        /// <summary> Checks to see if there are web logs that need to be processed to the usage statistics </summary>
        /// <param name="Settings"> Instance-wide settings which may be required for this process </param>
        public override void DoWork(InstanceWide_Settings Settings)
        {
            // If there is no IIS web log set, then do nothing.  Don't even need a log here.
            if (String.IsNullOrEmpty(Settings.Builder.IIS_Logs_Directory))
            {
                return;
            }

            // Just don't run the first day of the month - ensures logs still not being written
            if (DateTime.Now.Day < 2)
            {
                return;
            }

            // Ensure directory exists and is accessible
            string log_directory = Settings.Builder.IIS_Logs_Directory;

            try
            {
                if (!Directory.Exists(log_directory))
                {
                    OnError("CalculateUsageStatisticsModule : IIS web log directory ( " + log_directory + " ) does not exists or is inaccessible", null, null, -1);
                    return;
                }
            }
            catch (Exception ee)
            {
                OnError("CalculateUsageStatisticsModule : IIS web log directory ( " + log_directory + " ) does not exists or is inaccessible : " + ee.Message, null, null, -1);
                return;
            }

            // Get the temporary workspace directory, and ensure it exists
            string temporary_workspace = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Temporary", "CalculateUsageStatisticsModule");

            try
            {
                if (!Directory.Exists(temporary_workspace))
                {
                    Directory.CreateDirectory(temporary_workspace);
                }
            }
            catch (Exception ee)
            {
                OnError("CalculateUsageStatisticsModule : Unable to create the temporary workspace ( " + temporary_workspace + " ) : " + ee.Message, null, null, -1);
                return;
            }

            // Clear the temporary workspace
            try
            {
                string[] files = Directory.GetFiles(temporary_workspace);
                foreach (string thisFile in files)
                {
                    File.Delete(thisFile);
                }
            }
            catch (Exception ee)
            {
                OnError("CalculateUsageStatisticsModule : Error caught clearing existing files from the temporary workspace ( " + temporary_workspace + " ) : " + ee.Message, null, null, -1);
                return;
            }


            // Get (and double check) the web directory
            if (String.IsNullOrEmpty(Settings.Servers.Application_Server_Network))
            {
                OnError("CalculateUsageStatisticsModule : No application server network setting!  Correct ASAP!", null, null, -1);
                return;
            }

            // Ensure directory exists and is accessible
            string sobekcm_directory = Settings.Servers.Application_Server_Network;

            try
            {
                if (!Directory.Exists(sobekcm_directory))
                {
                    OnError("CalculateUsageStatisticsModule : Web application server network directory ( " + sobekcm_directory + " ) does not exists or is inaccessible", null, null, -1);
                    return;
                }
            }
            catch (Exception ee)
            {
                OnError("CalculateUsageStatisticsModule : Web application server network  ( " + sobekcm_directory + " ) does not exists or is inaccessible : " + ee.Message, null, null, -1);
                return;
            }

            // Determine which year/months already have been analyzed for this instance
            Statistics_Dates statsDates = new Statistics_Dates();

            if (Engine_ApplicationCache_Gateway.Stats_Date_Range != null)
            {
                Engine_Database.Populate_Statistics_Dates(statsDates, null);
            }
            else
            {
                statsDates = Engine_ApplicationCache_Gateway.Stats_Date_Range;
            }

            // Get the list of all IIS web logs
            string[] log_files = Directory.GetFiles(log_directory, "u_ex*.log");

            // If no log files, just return
            if (log_files.Length == 0)
            {
                OnError("CalculateUsageStatisticsModule : No IIS web logs found in directory  ( " + log_directory + " )", null, null, -1);
                return;
            }

            // Get the earliest and latest log files from the IIS web logs
            string earliest = "ZZZZZZZZ";
            string latest   = "AAAAAAAA";

            foreach (string thisFile in log_files)
            {
                string thisFileName = Path.GetFileNameWithoutExtension(thisFile);
                if (String.Compare(thisFileName, earliest, StringComparison.OrdinalIgnoreCase) < 0)
                {
                    earliest = thisFileName;
                }
                if (String.Compare(thisFileName, latest, StringComparison.OrdinalIgnoreCase) > 0)
                {
                    latest = thisFileName;
                }
            }

            // Parse them to determine the earliest and latest year/months
            int earliest_year;
            int earliest_month;
            int latest_year;
            int latest_month;

            try
            {
                earliest_year  = 2000 + Int32.Parse(earliest.Substring(4, 2));
                earliest_month = Int32.Parse(earliest.Substring(6, 2));
                latest_year    = 2000 + Int32.Parse(latest.Substring(4, 2));
                latest_month   = Int32.Parse(latest.Substring(6, 2));
            }
            catch (Exception)
            {
                OnError("CalculateUsageStatisticsModule : Error parsing the earliest or latest log for year/month (" + earliest + " or " + latest + " )", null, null, -1);
                return;
            }



            // Determine what years/months are missing
            List <string> year_month = new List <string>();

            if (statsDates.Earliest_Year == 2000)
            {
                // No stats every collected, so collect them all
                int curr_year  = earliest_year;
                int curr_month = earliest_month;
                while ((curr_year < latest_year) || ((curr_year == latest_year) && (curr_month <= latest_month)))
                {
                    if ((curr_year == DateTime.Now.Year) && (curr_month == DateTime.Now.Month))
                    {
                        break;
                    }

                    year_month.Add(curr_year + curr_month.ToString().PadLeft(2, '0'));

                    curr_month++;
                    if (curr_month > 12)
                    {
                        curr_year++;
                        curr_month = 1;
                    }
                }
            }
            else
            {
                // No stats every collected, so collect them all
                int curr_year  = earliest_year;
                int curr_month = earliest_month;
                while ((curr_year < latest_year) || ((curr_year == latest_year) && (curr_month <= latest_month)))
                {
                    if ((curr_year == DateTime.Now.Year) && (curr_month == DateTime.Now.Month))
                    {
                        break;
                    }

                    if ((curr_year > statsDates.Latest_Year) || ((curr_year == statsDates.Latest_Year) && (curr_month > statsDates.Latest_Month)))
                    {
                        year_month.Add(curr_year + curr_month.ToString().PadLeft(2, '0'));
                    }

                    curr_month++;
                    if (curr_month > 12)
                    {
                        curr_year++;
                        curr_month = 1;
                    }
                }
            }

            // If no year/months were added , then no work to do
            if (year_month.Count == 0)
            {
                return;
            }

            // Create the processor
            SobekCM_Stats_Reader_Processor processor = new SobekCM_Stats_Reader_Processor(log_directory, temporary_workspace, sobekcm_directory, year_month);

            processor.New_Status += processor_New_Status;

            // Create the thread
            processor.Process_IIS_Logs();

            // Delete the cached file, if one exists
            try
            {
                string temp_directory = Path.Combine(Settings.Servers.Application_Server_Network, "temp");
                if (Directory.Exists(temp_directory))
                {
                    string cache_xml_file = Path.Combine(temp_directory, "overall_usage.xml");
                    if (File.Exists(cache_xml_file))
                    {
                        File.Delete(cache_xml_file);
                    }
                }
            }
            catch { }

            // Shoudl emails be sent?
            if (Settings.Builder.Send_Usage_Emails)
            {
                // Load the text
                string possible_email_body_dir = Path.Combine(Settings.Servers.Application_Server_Network, "design", "extra", "stats");
                Usage_Stats_Email_Helper.Set_Email_Body(Path.Combine(possible_email_body_dir, "stats_email_body.txt"));

                // Send emails for each year/month (in order)
                foreach (string thisYearMonth in year_month)
                {
                    int year  = Convert.ToInt32(thisYearMonth.Substring(0, 4));
                    int month = Convert.ToInt32(thisYearMonth.Substring(4, 2));

                    Send_Usage_Emails(year, month, Settings.Servers.System_Base_URL, Settings.System.System_Name, Settings.Email.Setup.DefaultFromAddress, Settings.Email.Setup.DefaultFromDisplay);
                }
            }
        }
        /// <summary> Constructor for a new instance of the MySobek_HtmlSubwriter class </summary>
        /// <param name="Results_Statistics"> Information about the entire set of results for a browse of a user's bookshelf folder </param>
        /// <param name="Paged_Results"> Single page of results for a browse of a user's bookshelf folder, within the entire set </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Item">Current item to edit, if the user is requesting to edit an item</param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="IP_Restrictions"> List of all IP Restriction ranges in use by this digital library </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the home page are organized </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public MySobek_HtmlSubwriter(Search_Results_Statistics Results_Statistics,
                                     List <iSearch_Title_Result> Paged_Results,
                                     Aggregation_Code_Manager Code_Manager,
                                     Item_Lookup_Object All_Items_Lookup,
                                     Item_Aggregation Hierarchy_Object,
                                     SobekCM_Skin_Object HTML_Skin,
                                     Language_Support_Info Translator,
                                     SobekCM_Navigation_Object Current_Mode,
                                     SobekCM_Item Current_Item,
                                     Dictionary <string, string> Aggregation_Aliases,
                                     SobekCM_Skin_Collection Web_Skin_Collection,
                                     User_Object Current_User,
                                     IP_Restriction_Ranges IP_Restrictions,
                                     Dictionary <string, Wordmark_Icon> Icon_Table,
                                     Portal_List URL_Portals,
                                     Statistics_Dates Stats_Date_Range,
                                     List <Thematic_Heading> Thematic_Headings,
                                     Custom_Tracer Tracer)
        {
            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Saving values and geting user object back from the session");

            resultsStatistics = Results_Statistics;
            pagedResults      = Paged_Results;
            codeManager       = Code_Manager;
            itemList          = All_Items_Lookup;
            htmlSkin          = HTML_Skin;
            translator        = Translator;
            currentCollection = Hierarchy_Object;
            currentItem       = Current_Item;
            user           = Current_User;
            ipRestrictions = IP_Restrictions;
            iconTable      = Icon_Table;
            statsDates     = Stats_Date_Range;


            if (Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Log_Out)
            {
                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Performing logout");

                HttpContext.Current.Session["user"] = null;
                HttpContext.Current.Response.Redirect("?");
            }

            if ((Current_Mode.My_Sobek_Type != My_Sobek_Type_Enum.Logon) && (user != null) && (user.Is_Temporary_Password))
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.New_Password;
            }

            if (Current_Mode.Logon_Required)
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
            }

            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Building the my sobek viewer object");
            switch (Current_Mode.My_Sobek_Type)
            {
            case My_Sobek_Type_Enum.Home:
                mySobekViewer = new Home_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.New_Item:
                mySobekViewer = new New_Group_And_Item_MySobekViewer(user, Current_Mode, itemList, codeManager, iconTable, htmlSkin, translator, Tracer);
                break;

            case My_Sobek_Type_Enum.Folder_Management:
                mySobekViewer = new Folder_Mgmt_MySobekViewer(user, resultsStatistics, pagedResults, codeManager, itemList, currentCollection, htmlSkin, translator, Current_Mode, Tracer);
                break;

            case My_Sobek_Type_Enum.Saved_Searches:
                mySobekViewer = new Saved_Searches_MySobekViewer(user, translator, Current_Mode, Tracer);
                break;

            case My_Sobek_Type_Enum.Preferences:
                mySobekViewer = new Preferences_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.Logon:
                mySobekViewer = new Logon_MySobekViewer(Current_Mode, Tracer);
                break;

            case My_Sobek_Type_Enum.New_Password:
                mySobekViewer = new NewPassword_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.Delete_Item:
                mySobekViewer = new Delete_Item_MySobekViewer(user, Current_Mode, All_Items_Lookup, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Item_Behaviors:
                mySobekViewer = new Edit_Item_Behaviors_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Item_Metadata:
                mySobekViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, currentItem, codeManager, iconTable, htmlSkin, Tracer);
                break;

            case My_Sobek_Type_Enum.File_Management:
                mySobekViewer = new File_Management_MySobekViewer(user, Current_Mode, Current_Item, itemList, codeManager, iconTable, htmlSkin, translator, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Group_Behaviors:
                mySobekViewer = new Edit_Group_Behaviors_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Group_Serial_Hierarchy:
                mySobekViewer = new Edit_Serial_Hierarchy_MySobekViewer(user);
                break;

            case My_Sobek_Type_Enum.Group_Add_Volume:
                // Pull the list of items tied to this group
                SobekCM_Items_In_Title itemsInTitle = Cached_Data_Manager.Retrieve_Items_In_Title(currentItem.BibID, Tracer);
                if (itemsInTitle == null)
                {
                    // Get list of information about this item group and save the item list
                    DataSet itemDetails = SobekCM_Database.Get_Item_Group_Details(currentItem.BibID, Tracer);
                    itemsInTitle = new SobekCM_Items_In_Title(itemDetails.Tables[1]);

                    // Store in cache if retrieved
                    Cached_Data_Manager.Store_Items_In_Title(currentItem.BibID, itemsInTitle, Tracer);
                }
                mySobekViewer = new Group_Add_Volume_MySobekViewer(user, Current_Mode, itemList, currentItem, codeManager, iconTable, htmlSkin, itemsInTitle, translator, Tracer);
                break;

            case My_Sobek_Type_Enum.Group_AutoFill_Volumes:
                mySobekViewer = new Group_AutoFill_Volume_MySobekViewer(user);
                break;

            case My_Sobek_Type_Enum.Group_Mass_Update_Items:
                mySobekViewer = new Mass_Update_Items_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                break;

            case My_Sobek_Type_Enum.User_Tags:
                mySobekViewer = new User_Tags_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.User_Usage_Stats:
                mySobekViewer = new User_Usage_Stats_MySobekViewer(user, Current_Mode, statsDates, Tracer);
                break;
            }

            // Pass in the navigation and translator information
            mySobekViewer.CurrentMode = Current_Mode;
            mySobekViewer.Translator  = translator;
        }
        /// <summary> Constructor for a new instance of the Admin_HtmlSubwriter class </summary>
        /// <param name="Results_Statistics"> Information about the entire set of results for a browse of a user's bookshelf folder </param>
        /// <param name="Paged_Results"> Single page of results for a browse of a user's bookshelf folder, within the entire set </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Item">Current item to edit, if the user is requesting to edit an item</param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="IP_Restrictions"> List of all IP Restriction ranges in use by this digital library </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the home page are organized </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Admin_HtmlSubwriter(Search_Results_Statistics Results_Statistics,
                                   List <iSearch_Title_Result> Paged_Results,
                                   Aggregation_Code_Manager Code_Manager,
                                   Item_Lookup_Object All_Items_Lookup,
                                   Item_Aggregation Hierarchy_Object,
                                   SobekCM_Skin_Object HTML_Skin,
                                   Language_Support_Info Translator,
                                   SobekCM_Navigation_Object Current_Mode,
                                   SobekCM_Item Current_Item,
                                   Dictionary <string, string> Aggregation_Aliases,
                                   SobekCM_Skin_Collection Web_Skin_Collection,
                                   User_Object Current_User,
                                   IP_Restriction_Ranges IP_Restrictions,
                                   Dictionary <string, Wordmark_Icon> Icon_Table,
                                   Portal_List URL_Portals,
                                   Statistics_Dates Stats_Date_Range,
                                   List <Thematic_Heading> Thematic_Headings,
                                   Custom_Tracer Tracer)
        {
            Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Saving values and geting user object back from the session");

            resultsStatistics = Results_Statistics;
            pagedResults      = Paged_Results;
            codeManager       = Code_Manager;
            itemList          = All_Items_Lookup;
            htmlSkin          = HTML_Skin;
            translator        = Translator;
            currentCollection = Hierarchy_Object;
            currentItem       = Current_Item;
            user           = Current_User;
            ipRestrictions = IP_Restrictions;
            iconTable      = Icon_Table;
            statsDates     = Stats_Date_Range;


            if (Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Log_Out)
            {
                Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Performing logout");

                HttpContext.Current.Session["user"] = null;
                HttpContext.Current.Response.Redirect("?");
            }

            if ((Current_Mode.My_Sobek_Type != My_Sobek_Type_Enum.Logon) && (user != null) && (user.Is_Temporary_Password))
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.New_Password;
            }

            if (Current_Mode.Logon_Required)
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
            }

            // If the user is not an admin, and admin was selected, reroute this
            if ((!Current_User.Is_System_Admin) && (!Current_User.Is_Portal_Admin))
            {
                Current_Mode.Mode             = Display_Mode_Enum.My_Sobek;
                Current_Mode.My_Sobek_Type    = My_Sobek_Type_Enum.Home;
                Current_Mode.My_Sobek_SubMode = String.Empty;
                HttpContext.Current.Response.Redirect(Current_Mode.Redirect_URL());
            }

            Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Building the my sobek viewer object");
            switch (Current_Mode.Admin_Type)
            {
            case Admin_Type_Enum.Aggregation_Single:
                adminViewer = new Aggregation_Single_AdminViewer(user, Current_Mode, codeManager, Thematic_Headings, Web_Skin_Collection, Tracer);
                break;

            case Admin_Type_Enum.Home:
                adminViewer = new Home_AdminViewer(user, Current_Mode, Tracer);
                break;

            case Admin_Type_Enum.Builder_Status:
                adminViewer = new Builder_AdminViewer(user, Current_Mode);
                break;

            case Admin_Type_Enum.Interfaces:
                adminViewer = new Skins_AdminViewer(user, Current_Mode, Web_Skin_Collection, Tracer);
                break;

            case Admin_Type_Enum.Forwarding:
                adminViewer = new Aliases_AdminViewer(user, Current_Mode, Aggregation_Aliases, Tracer);
                break;

            case Admin_Type_Enum.Wordmarks:
                adminViewer = new Wordmarks_AdminViewer(user, Current_Mode, Tracer);
                break;

            case Admin_Type_Enum.URL_Portals:
                adminViewer = new Portals_AdminViewer(user, Current_Mode, URL_Portals, Tracer);
                break;

            case Admin_Type_Enum.Users:
                adminViewer = new Users_AdminViewer(user, Current_Mode, codeManager, Tracer);
                break;

            case Admin_Type_Enum.User_Groups:
                adminViewer = new User_Group_AdminViewer(user, Current_Mode, codeManager, Tracer);
                break;

            case Admin_Type_Enum.Aggregations_Mgmt:
                adminViewer = new Aggregations_Mgmt_AdminViewer(user, Current_Mode, codeManager, Tracer);
                break;

            case Admin_Type_Enum.IP_Restrictions:
                adminViewer = new IP_Restrictions_AdminViewer(user, Current_Mode, ipRestrictions, Tracer);
                break;

            case Admin_Type_Enum.Thematic_Headings:
                adminViewer = new Thematic_Headings_AdminViewer(user, Current_Mode, Thematic_Headings, Tracer);
                break;

            case Admin_Type_Enum.Settings:
                adminViewer = new Settings_AdminViewer(user, Current_Mode, Tracer);
                break;

            case Admin_Type_Enum.Projects:
                if (Current_Mode.My_Sobek_SubMode.Length > 1)
                {
                    string project_code = Current_Mode.My_Sobek_SubMode.Substring(1);
                    Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Checking cache for valid project file");
                    if (user != null)
                    {
                        SobekCM_Item projectObject = Cached_Data_Manager.Retrieve_Project(user.UserID, project_code, Tracer);
                        if (projectObject != null)
                        {
                            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Valid project file found in cache");
                            adminViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, projectObject, codeManager, iconTable, htmlSkin, Tracer);
                        }
                        else
                        {
                            if (SobekCM_Database.Get_All_Projects_Templates(Tracer).Tables[0].Select("ProjectCode='" + project_code + "'").Length > 0)
                            {
                                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Building project file from (possible) PMETS");
                                string       pmets_file = SobekCM_Library_Settings.Base_MySobek_Directory + "projects\\" + Current_Mode.My_Sobek_SubMode.Substring(1) + ".pmets";
                                SobekCM_Item pmets_item = File.Exists(pmets_file) ? SobekCM_Item.Read_METS(pmets_file) : new SobekCM_Item();
                                pmets_item.Bib_Info.Main_Title.Title = "Project level metadata for '" + project_code + "'";
                                pmets_item.Bib_Info.SobekCM_Type     = TypeOfResource_SobekCM_Enum.Project;
                                pmets_item.BibID            = project_code.ToUpper();
                                pmets_item.VID              = "00001";
                                pmets_item.Source_Directory = SobekCM_Library_Settings.Base_MySobek_Directory + "projects\\";

                                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Adding project file to cache");

                                Cached_Data_Manager.Store_Project(user.UserID, project_code, pmets_item, Tracer);

                                adminViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, pmets_item, codeManager, iconTable, htmlSkin, Tracer);
                            }
                        }
                    }
                }

                if (adminViewer == null)
                {
                    adminViewer = new Projects_AdminViewer(user, Current_Mode, Tracer);
                }
                break;
            }

            // Pass in the navigation and translator information
            adminViewer.CurrentMode = Current_Mode;
            adminViewer.Translator  = translator;
        }