Inheritance: MetadataDescribableBase
Exemplo n.º 1
0
        /// <summary> Adds a file (with the appropriate divisions and pages) to this tree by filename  </summary>
        /// <param name="FileName"> Name of the file to add </param>
        /// <param name="Label"> Label for the page containing this file, if it is a new page </param>
        /// <returns> Newly built <see cref="SobekCM_File_Info" /> object which has been added to this tree </returns>
        /// <remarks> This is generally used to add just a single file.  To add many files, better logic should be implemented </remarks>
        public SobekCM_File_Info Add_File(string FileName, string Label)
        {
            SobekCM_File_Info newFile = new SobekCM_File_Info(FileName);

            Add_File(newFile, Label);
            return(newFile);
        }
        /// <summary> Computes the attributes (width, height) for a JPEG file </summary>
        /// <param name="JPEG_File"> METS SobekCM_File_Info object for this jpeg file </param>
        /// <param name="File_Location"> Location where this file exists </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> The attribute information is computed and then stored in the provided METS SobekCM_File_Info object </remarks>
        private bool Compute_Jpeg_Attributes(SobekCM_File_Info JPEG_File, string File_Location)
        {
            // If the width and height are already determined, done!
            if ((JPEG_File.Width > 0) && (JPEG_File.Height > 0))
                return true;

            // Does this file exist?
            if (File.Exists(File_Location + "/" + JPEG_File.System_Name))
            {
                try
                {
                    // Get the height and width of this JPEG file
                    Bitmap image = (Bitmap)Image.FromFile(File_Location + "/" + JPEG_File.System_Name);
                    JPEG_File.Width = (ushort)image.Width;
                    JPEG_File.Height = (ushort)image.Height;
                    image.Dispose();
                    return true;
                }
                catch
                {
                    return false;
                }
            }

            return false;
        }
Exemplo n.º 3
0
        /// <summary> Adds a file  object (with the appropriate divisions and pages) to this tree </summary>
        /// <param name="New_File"> New file object to add </param>
        /// <param name="Label"> Label for the page containing this file, if it is a new page </param>
        /// <remarks> This is generally used to add just a single file.  To add many files, better logic should be implemented </remarks>
        public void Add_File(SobekCM_File_Info New_File, string Label)
        {
            // Determine the upper case name
            string systemname_upper = New_File.File_Name_Sans_Extension;

            // Look for a page/entity which has the same file name, else it will be added to the last division
            foreach (abstract_TreeNode rootNode in Roots)
            {
                if (recursively_add_file(rootNode, New_File, systemname_upper))
                {
                    return;
                }
            }

            // If not found, find the last division
            if (Roots.Count > 0)
            {
                if (!Roots[Roots.Count - 1].Page)
                {
                    // Get his last division
                    Division_TreeNode lastDivision = (Division_TreeNode)Roots[Roots.Count - 1];

                    // Find the last division then
                    while ((lastDivision.Nodes.Count > 0) && (!lastDivision.Nodes[lastDivision.Nodes.Count - 1].Page))
                    {
                        lastDivision = (Division_TreeNode)lastDivision.Nodes[lastDivision.Nodes.Count - 1];
                    }

                    // Add this as a new page on the last division
                    Page_TreeNode newPage = new Page_TreeNode(Label);
                    lastDivision.Add_Child(newPage);

                    // Now, add this file to the page
                    newPage.Files.Add(New_File);
                }
                else
                {
                    // No divisions at all, but pages exist at the top level, which is okay
                    Page_TreeNode pageNode = (Page_TreeNode)Roots[Roots.Count - 1];

                    // Now, add this file to the page
                    pageNode.Files.Add(New_File);
                }
            }
            else
            {
                // No nodes exist, so add a MAIN division node
                Division_TreeNode newDivNode = new Division_TreeNode("Main", String.Empty);
                Roots.Add(newDivNode);

                // Add this as a new page on the new division
                Page_TreeNode newPage = new Page_TreeNode(Label);
                newDivNode.Add_Child(newPage);

                // Now, add this file to the page
                newPage.Files.Add(New_File);
            }
        }
        /// <summary> Computes the attributes (width, height) for a JPEG2000 file </summary>
        /// <param name="JPEG2000_File"> METS SobekCM_File_Info object for this jpeg2000 file </param>
        /// <param name="File_Location"> Location where this file exists </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> The attribute information is computed and then stored in the provided METS SobekCM_File_Info object </remarks>
        private bool Compute_Jpeg2000_Attributes(SobekCM_File_Info JPEG2000_File, string File_Location)
        {
            // If the width and height are already determined, done!
            if ((JPEG2000_File.Width > 0) && (JPEG2000_File.Height > 0) && (JPEG2000_File.System_Name.Length > 0))
                return true;

            // Does this file exist?
            if (File.Exists(File_Location + "/" + JPEG2000_File.System_Name))
            {
                return get_attributes_from_jpeg2000(JPEG2000_File, File_Location + "/" + JPEG2000_File.System_Name);
            }

            if ((JPEG2000_File.System_Name.Length > 0) && (File.Exists(JPEG2000_File.System_Name)))
            {
                return get_attributes_from_jpeg2000(JPEG2000_File, JPEG2000_File.System_Name);
            }

            return false;
        }
Exemplo n.º 5
0
        private bool recursively_add_file(abstract_TreeNode Node, SobekCM_File_Info New_File, string SystemName_Upper)
        {
            // If this is a page, check for a match first
            if (Node.Page)
            {
                Page_TreeNode pageNode = (Page_TreeNode)Node;
                if (pageNode.Files.Count >= 1)
                {
                    if (pageNode.Files[0].File_Name_Sans_Extension == SystemName_Upper)
                    {
                        // Belongs to this page.  Now, just make sure it doesn't already exist
                        foreach (SobekCM_File_Info thisFile in pageNode.Files)
                        {
                            if (thisFile.System_Name.ToUpper() == New_File.System_Name.ToUpper())
                            {
                                return(true);
                            }
                        }

                        // Not found, so add it to this page
                        pageNode.Files.Add(New_File);
                        return(true);
                    }
                }
            }

            // If this was a division, check all pages
            if (!Node.Page)
            {
                Division_TreeNode divNode = (Division_TreeNode)Node;
                foreach (abstract_TreeNode childNodes in divNode.Nodes)
                {
                    if (recursively_add_file(childNodes, New_File, SystemName_Upper))
                    {
                        return(true);
                    }
                }
            }

            // If nothing found that matches under this node, return false
            return(false);
        }
        /// <summary> Computes the attributes (width, height) for a JPEG file </summary>
        /// <param name="JPEG_File"> METS SobekCM_File_Info object for this jpeg file </param>
        /// <param name="File_Location"> Location where this file exists </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> The attribute information is computed and then stored in the provided METS SobekCM_File_Info object </remarks>
        private bool Compute_Jpeg_Attributes(SobekCM_File_Info JPEG_File, string File_Location)
        {
            // Does this file exist?
            string file_in_place = Path.Combine(File_Location, JPEG_File.System_Name);
            if (File.Exists(file_in_place))
            {
                try
                {
                    // Get the height and width of this JPEG file
                    Bitmap image = (Bitmap)Image.FromFile(file_in_place);
                    JPEG_File.Width = (ushort)image.Width;
                    JPEG_File.Height = (ushort)image.Height;
                    image.Dispose();
                    return true;
                }
                catch
                {
                    return false;
                }
            }

            return false;
        }
        private bool complete_item_submission(SobekCM_Item Item_To_Complete, Custom_Tracer Tracer)
        {
            // Set an initial flag
            criticalErrorEncountered = false;
            bool xml_found = false;

            // This package is good to go, so build it, save, etc...
            try
            {
                // Save the METS file to the database and back to the directory
                Item_To_Complete.Source_Directory = userInProcessDirectory;

                // Now, add the TEI file
                SobekCM_File_Info tei_newFile = new SobekCM_File_Info(Path.GetFileName(new_tei_file));
                string tei_label = Path.GetFileName(new_tei_file) + " (TEI)";
                Item_To_Complete.Divisions.Download_Tree.Add_File(tei_newFile, tei_label);

                // Save to the database
                try
                {
                    SobekCM_Item_Updater.Update_Item(Item_To_Complete, RequestSpecificValues.Current_User, out error_message);

                    CachedDataManager.Items.Remove_Digital_Resource_Object(RequestSpecificValues.Current_User.UserID, Item_To_Complete.BibID, Item_To_Complete.VID, null);

                    // Also clear the engine
                    SobekEngineClient.Items.Clear_Item_Cache(Item_To_Complete.BibID, Item_To_Complete.VID, RequestSpecificValues.Tracer);
                }
                catch (Exception ee)
                {
                    StreamWriter writer = new StreamWriter(userInProcessDirectory + "\\exception.txt", false);
                    writer.WriteLine("ERROR CAUGHT WHILE SAVING NEW DIGITAL RESOURCE");
                    writer.WriteLine(DateTime.Now.ToString());
                    writer.WriteLine();
                    writer.WriteLine(ee.Message);
                    writer.WriteLine(ee.StackTrace);
                    writer.Flush();
                    writer.Close();
                    throw;
                }

                // Assign the file root and assoc file path
                Item_To_Complete.Web.File_Root = Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8, 2);
                Item_To_Complete.Web.AssocFilePath = Item_To_Complete.Web.File_Root + "\\" + Item_To_Complete.VID + "\\";

                // Save the item settings
                SobekCM_Item_Database.Set_Item_Setting_Value(Item_To_Complete.Web.ItemID, "TEI.Source_File", Path.GetFileName(new_tei_file));
                SobekCM_Item_Database.Set_Item_Setting_Value(Item_To_Complete.Web.ItemID, "TEI.CSS", css_file);
                SobekCM_Item_Database.Set_Item_Setting_Value(Item_To_Complete.Web.ItemID, "TEI.Mapping", mapping_file);

                // Find the actual XSLT file
                string xslt_directory = Path.Combine(UI_ApplicationCache_Gateway.Settings.Servers.Application_Server_Network, "plugins", "tei", "xslt");
                string[] xslt_files = Directory.GetFiles(xslt_directory, xslt_file + ".xsl*");
                SobekCM_Item_Database.Set_Item_Setting_Value(Item_To_Complete.Web.ItemID, "TEI.XSLT", Path.GetFileName(xslt_files[0]));

                // Add the TEI viewer
                SobekCM_Item_Database.Save_Item_Add_Viewer(Item_To_Complete.Web.ItemID, "TEI", new_tei_file.Replace(".xml", "").Replace(".XML", "") + " (TEI)", new_tei_file);

                // Create the static html pages
                string base_url = RequestSpecificValues.Current_Mode.Base_URL;
                try
                {
                    Static_Pages_Builder staticBuilder = new Static_Pages_Builder(UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL, UI_ApplicationCache_Gateway.Settings.Servers.Base_Data_Directory, RequestSpecificValues.HTML_Skin.Skin_Code);
                    string filename = userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html";
                    staticBuilder.Create_Item_Citation_HTML(Item_To_Complete, filename, String.Empty);

                    // Copy the static HTML file to the web server
                    try
                    {
                        if (!Directory.Exists(UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + item.BibID.Substring(0, 2) + "\\" + item.BibID.Substring(2, 2) + "\\" + item.BibID.Substring(4, 2) + "\\" + item.BibID.Substring(6, 2) + "\\" + item.BibID.Substring(8)))
                            Directory.CreateDirectory(UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + item.BibID.Substring(0, 2) + "\\" + item.BibID.Substring(2, 2) + "\\" + item.BibID.Substring(4, 2) + "\\" + item.BibID.Substring(6, 2) + "\\" + item.BibID.Substring(8));
                        if (File.Exists(userInProcessDirectory + "\\" + item.BibID + "_" + item.VID + ".html"))
                            File.Copy(userInProcessDirectory + "\\" + item.BibID + "_" + item.VID + ".html", UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + item.BibID.Substring(0, 2) + "\\" + item.BibID.Substring(2, 2) + "\\" + item.BibID.Substring(4, 2) + "\\" + item.BibID.Substring(6, 2) + "\\" + item.BibID.Substring(8) + "\\" + item.BibID + "_" + item.VID + ".html", true);
                    }
                    catch (Exception)
                    {
                        // This is not critical
                    }
                }
                catch (Exception)
                {
                    // An error here is not catastrophic
                }

                RequestSpecificValues.Current_Mode.Base_URL = base_url;

                // Save the rest of the metadata
                Item_To_Complete.Save_SobekCM_METS();

                // Create the options dictionary used when saving information to the database, or writing MarcXML
                Dictionary<string, object> options = new Dictionary<string, object>();
                if (UI_ApplicationCache_Gateway.Settings.MarcGeneration != null)
                {
                    options["MarcXML_File_ReaderWriter:MARC Cataloging Source Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Cataloging_Source_Code;
                    options["MarcXML_File_ReaderWriter:MARC Location Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Location_Code;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Agency"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Agency;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Place"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Place;
                    options["MarcXML_File_ReaderWriter:MARC XSLT File"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.XSLT_File;
                }
                options["MarcXML_File_ReaderWriter:System Name"] = UI_ApplicationCache_Gateway.Settings.System.System_Name;
                options["MarcXML_File_ReaderWriter:System Abbreviation"] = UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation;

                // Save the marc xml file
                MarcXML_File_ReaderWriter marcWriter = new MarcXML_File_ReaderWriter();
                string errorMessage;
                marcWriter.Write_Metadata(Item_To_Complete.Source_Directory + "\\marc.xml", Item_To_Complete, options, out errorMessage);

                // Delete the TEMP mets file
                if (File.Exists(userInProcessDirectory + "\\TEMP000001_00001.mets"))
                    File.Delete(userInProcessDirectory + "\\TEMP000001_00001.mets");

                // Rename the METS file to the XML file
                if ((!File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets.xml")) &&
                    (File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets")))
                {
                    File.Move(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets", userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets.xml");
                }

                string serverNetworkFolder = UI_ApplicationCache_Gateway.Settings.Servers.Image_Server_Network + Item_To_Complete.Web.AssocFilePath;

                // Create the folder
                if (!Directory.Exists(serverNetworkFolder))
                    Directory.CreateDirectory(serverNetworkFolder);
                if (!Directory.Exists(serverNetworkFolder + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name))
                    Directory.CreateDirectory(serverNetworkFolder + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name);

                // Copy the static HTML page over first
                if (File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html"))
                {
                    File.Copy(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html", serverNetworkFolder + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name + "\\" + item.BibID + "_" + item.VID + ".html", true);
                    File.Delete(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html");
                }

                // Copy all the files
                string[] allFiles = Directory.GetFiles(userInProcessDirectory);
                foreach (string thisFile in allFiles)
                {
                    string destination_file = serverNetworkFolder + "\\" + (new FileInfo(thisFile)).Name;
                    File.Copy(thisFile, destination_file, true);
                }

                // Add this to the cache
                UI_ApplicationCache_Gateway.Items.Add_SobekCM_Item(Item_To_Complete);

                // Now, delete all the files here
                string[] all_files = Directory.GetFiles(userInProcessDirectory);
                foreach (string thisFile in all_files)
                {
                    File.Delete(thisFile);
                }

                // Always set the additional work needed flag, to give the builder a  chance to look at it
                SobekCM_Database.Update_Additional_Work_Needed_Flag(Item_To_Complete.Web.ItemID, true, Tracer);

            }
            catch (Exception ee)
            {
                validationErrors.Add("Error encountered during item save!");
                validationErrors.Add(ee.ToString().Replace("\r", "<br />"));

                // Set an initial flag
                criticalErrorEncountered = true;

                string error_body = "<strong>ERROR ENCOUNTERED DURING ONLINE SUBMITTAL PROCESS</strong><br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a><br />User: "******"<br /><br /></blockquote>" + ee.ToString().Replace("\n", "<br />");
                string error_subject = "Error during submission for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                string email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Error_Email;
                if (email_to.Length == 0)
                    email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Email;
                Email_Helper.SendEmail(email_to, error_subject, error_body, true, RequestSpecificValues.Current_Mode.Instance_Name);
            }

            // Also clear some values from the session
            HttpContext.Current.Session["Edit_TEI_Item_MySobekViewer." + bibid + "_" + vid + ".Mapping_File"] = null;
            HttpContext.Current.Session["Edit_TEI_Item_MySobekViewer." + bibid + "_" + vid + ".XSLT_File"] = null;
            HttpContext.Current.Session["Edit_TEI_Item_MySobekViewer." + bibid + "_" + vid + ".CSS_File"] = null;
            HttpContext.Current.Session["Edit_TEI_Item_MySobekViewer." + bibid + "_" + vid + ".Original_TEI_File"] = null;
            HttpContext.Current.Session["Edit_TEI_mySobekViewer." + bibid + "_" + vid + ".New_Item"] = null;

            if (!criticalErrorEncountered)
            {
                // Also clear any searches or browses ( in the future could refine this to only remove those
                // that are impacted by this save... but this is good enough for now )
                CachedDataManager.Clear_Search_Results_Browses();

                // Redirect to the item page
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Item_Display;
                RequestSpecificValues.Current_Mode.BibID = bibid;
                RequestSpecificValues.Current_Mode.VID = vid;
                UrlWriterHelper.Redirect(RequestSpecificValues.Current_Mode);
            }

            return criticalErrorEncountered;
        }
        //public void Set_Text_Language(Application_State.Language_Enum Language)
        //{
        //    switch (Language)
        //    {
        //        case Application_State.Language_Enum.French:
        //            search = "RECHERCHE";
        //            search_doc = "Recherche Ce Document";
        //            view = "VUE";
        //            full_citation = "Notice"; // "Citation Complètes";
        //            browse_images = "Revue des Images";
        //            view_image = "Revue l'Image";
        //            browse_text = "Revue la Texte";
        //            language = "LANGUE";
        //            english = "Anglais";
        //            french = "Français";
        //            spanish = "Espagñol";
        //            download = "TÉLÉCHARGEMENT";
        //            help = "AIDE";
        //            using_site = "Navigation";
        //            contact = "Assistance";
        //            contents = "TABLE DES MATIÈRES";
        //            break;
        //        case Application_State.Language_Enum.Spanish:
        //            search = "BUSCAR";
        //            search_all = "Busque Todas las Colecciones";
        //            search_this = "Busque Esta Colección";
        //            last_search = "Resultados Anteriores";
        //            search_doc = "Busque Este Documento";
        //            view = "VER";
        //            full_citation = "Cita Completa";
        //            browse_images = "Navegar Imagenes";
        //            view_image = "Ver Imagen";
        //            browse_text = "Navegar Texto";
        //            language = "IDIOMA";
        //            english = "Inglés";
        //            french = "Francés";
        //            spanish = "Español";
        //            download = "TRANSFERENCIA DIRECTA";
        //            help = "AYUDA";
        //            using_site = "Usando este sitio";
        //            contact = "Contacto";
        //            contents = "INDICE";
        //            break;
        //    }
        //}
        /// <summary> Writes the HTML generated by this item html subwriter directly to the response stream </summary>
        /// <param name="Output"> Stream to which to write the HTML for this subwriter </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <returns> Value indicating if html writer should finish the page immediately after this, or if there are other controls or routines which need to be called first </returns>
        /// <remarks> This begins writing this page, up to the item-level main menu</remarks>
        public override bool Write_HTML(TextWriter Output, Custom_Tracer Tracer)
        {
            Tracer.Add_Trace("Item_HtmlSubwriter.Write_HTML", "Begin writing the item viewer, up to the item-level main menu");

            // If this is for a fragment, do nothing
            if (!String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.Fragment))
                return false;

            Output.WriteLine();

            // Just return if this is the pageviewer
            if (PageViewer.ItemViewer_Type == ItemViewer_Type_Enum.GnuBooks_PageTurner)
            {
                return true;
            }

            // Put an itemscope div around here for micro-data purposes
            Output.WriteLine("<!-- Unstyled div placed around entire item information to support schema.org microdata -->");
            Output.WriteLine("<section itemscope itemtype=\"http:schema.org/ItemPage\">");
            Output.WriteLine();

            // The item viewer can choose to override the standard item titlebar
            if (!behaviors.Contains(HtmlSubwriter_Behaviors_Enum.Item_Subwriter_Suppress_Titlebar))
            {
                Output.WriteLine("<!-- Show the title and any other important item information -->");
                Output.WriteLine("<section id=\"sbkIsw_Titlebar\" role=\"banner\">");

                if (RequestSpecificValues.Current_Item.METS_Header.RecordStatus_Enum == METS_Record_Status.BIB_LEVEL)
                {
                    string grouptitle = RequestSpecificValues.Current_Item.Behaviors.GroupTitle;
                    if (grouptitle.Length > 125)
                    {
                        Output.WriteLine("\t<h1 itemprop=\"name\"><abbr title=\"" + grouptitle + "\">" + grouptitle.Substring(0, 120) + "..</abbr></h1>");
                    }
                    else
                    {
                        Output.WriteLine("\t<h1 itemprop=\"name\">" + grouptitle + "</h1>");
                    }
                }
                else
                {
                    string final_title = RequestSpecificValues.Current_Item.Bib_Info.Main_Title.Title;
                    if (RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort.Length > 0)
                    {
                        if (RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort[RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort.Length - 1] == ' ')
                            final_title = RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort + RequestSpecificValues.Current_Item.Bib_Info.Main_Title.Title;
                        else
                        {
                            if (RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort[RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort.Length - 1] == '\'')
                            {
                                final_title = RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort + RequestSpecificValues.Current_Item.Bib_Info.Main_Title.Title;
                            }
                            else
                            {
                                final_title = RequestSpecificValues.Current_Item.Bib_Info.Main_Title.NonSort + " " + RequestSpecificValues.Current_Item.Bib_Info.Main_Title.Title;
                            }
                        }
                    }

                    // Add the Title if there is one
                    if (final_title.Length > 0)
                    {
                        // Is this a newspaper?
                        bool newspaper = RequestSpecificValues.Current_Item.Behaviors.GroupType.ToUpper() == "NEWSPAPER";

                        // Does a custom setting override the default behavior to add a date?
                        if ((newspaper) && (UI_ApplicationCache_Gateway.Settings.Additional_Settings.ContainsKey("Item Viewer.Include Date In Title")) && (UI_ApplicationCache_Gateway.Settings.Additional_Settings["Item Viewer.Include Date In Title"].ToUpper() == "NEVER"))
                            newspaper = false;

                        // Add the date if it should be added
                        if ((newspaper) && ((RequestSpecificValues.Current_Item.Bib_Info.Origin_Info.Date_Created.Length > 0) || (RequestSpecificValues.Current_Item.Bib_Info.Origin_Info.Date_Issued.Length > 0)))
                        {
                            string date = RequestSpecificValues.Current_Item.Bib_Info.Origin_Info.Date_Created;
                            if (RequestSpecificValues.Current_Item.Bib_Info.Origin_Info.Date_Created.Length == 0)
                                date = RequestSpecificValues.Current_Item.Bib_Info.Origin_Info.Date_Issued;

                            if (final_title.Length > 125)
                            {
                                Output.WriteLine("\t<h1 itemprop=\"name\"><abbr title=\"" + final_title + "\">" + final_title.Substring(0, 120) + "..</abbr> ( " + date + " )</h1>");
                            }
                            else
                            {
                                Output.WriteLine("\t<h1 itemprop=\"name\">" + final_title + " ( " + date + " )</h1>");
                            }
                        }
                        else
                        {
                            if (final_title.Length > 125)
                            {
                                Output.WriteLine("\t<h1 itemprop=\"name\"><abbr title=\"" + final_title + "\">" + final_title.Substring(0, 120) + "..</abbr></h1>");
                            }
                            else
                            {
                                Output.WriteLine("\t<h1 itemprop=\"name\">" + final_title + "</h1>");
                            }
                        }
                    }

                    // Add the link if there is one
                    if ((RequestSpecificValues.Current_Item.Bib_Info.hasLocationInformation) && (RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL.Length > 0))
                    {
                        if (RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL.ToLower().IndexOf("www.youtube.com") < 0)
                        {

                            // Determine the type of link
                            string type = UI_ApplicationCache_Gateway.Translation.Get_Translation("Related Link", RequestSpecificValues.Current_Mode.Language);
                            if (RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL_Display_Label.Length > 0)
                            {
                                type = UI_ApplicationCache_Gateway.Translation.Get_Translation(RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL_Display_Label, RequestSpecificValues.Current_Mode.Language);
                            }

                            // Determine the display value
                            string note = RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL;
                            if (RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL_Note.Length > 0)
                            {
                                note = RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL_Note;
                            }

                            // Add the link
                            Output.WriteLine("\t<a href=\"" + RequestSpecificValues.Current_Item.Bib_Info.Location.Other_URL + "\">" + note + " ( " + type + " )</a><br />");
                        }
                    }

                    // If there is an ACCESSION number and this is an ARTIFACT, include that at the top
                    //EDIT: Removing the condition for checking if this is an ARTIFACT. Always display the ACCESSION number if available (6/18/2014 - SY)
              //      if ((RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.Artifact) && (RequestSpecificValues.Current_Item.Bib_Info.Identifiers_Count > 0))
                    if (RequestSpecificValues.Current_Item.Bib_Info.Identifiers_Count > 0)
                    {
                        foreach (Identifier_Info thisIdentifier in RequestSpecificValues.Current_Item.Bib_Info.Identifiers)
                        {
                            if (thisIdentifier.Type.ToUpper().IndexOf("ACCESSION") >= 0)
                            {
                                Output.WriteLine("\t" + UI_ApplicationCache_Gateway.Translation.Get_Translation("Accession number", RequestSpecificValues.Current_Mode.Language) + " " + thisIdentifier.Identifier + "<br />");
                                break;
                            }
                        }
                    }
                }

                Output.WriteLine("</section>");
                Output.WriteLine();
            }

            // The item viewer can choose to override the standard item menu
            if (!behaviors.Contains(HtmlSubwriter_Behaviors_Enum.Item_Subwriter_Suppress_Item_Menu))
            {
                // Can this user (if there is one) edit this item?
                bool canManage = (RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.Can_Edit_This_Item(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type_String, RequestSpecificValues.Current_Item.Bib_Info.Source.Code, RequestSpecificValues.Current_Item.Bib_Info.HoldingCode, RequestSpecificValues.Current_Item.Behaviors.Aggregation_Code_List));

                // Add the item views
                Output.WriteLine("<!-- Add the different view and social options -->");
                Output.WriteLine("<nav class=\"sbkMenu_Bar\" id=\"sbkIsw_MenuBar\" role=\"navigation\" aria-label=\"Item menu\">");
                Output.WriteLine("<h2 class=\"hidden-element\">Item menu</h2>");

                // Add the sharing buttons if this is not restricted by IP address or checked out
                if ((!itemRestrictedFromUserByIp) && (!itemCheckedOutByOtherUser) && (!RequestSpecificValues.Current_Mode.Is_Robot))
                {
                    string add_text = "Add";
                    string remove_text = "Remove";
                    string send_text = "Send";
                    string print_text = "Print";
                    if (canManage)
                    {
                        add_text = String.Empty;
                        remove_text = String.Empty;
                        send_text = String.Empty;
                        print_text = String.Empty;
                    }

                    string logOnUrl = String.Empty;
                    bool isLoggedOn = RequestSpecificValues.Current_User != null && RequestSpecificValues.Current_User.LoggedOn;
                    if ( !isLoggedOn )
                    {
                        string returnUrl = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);

                        RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.My_Sobek;
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
                        RequestSpecificValues.Current_Mode.Return_URL = returnUrl;
                        logOnUrl = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Item_Display;
                        RequestSpecificValues.Current_Mode.Return_URL = String.Empty;
                    }

                    Output.WriteLine("\t<div id=\"menu-right-actions\">");

                    if (RequestSpecificValues.Current_Item.Web.ItemID > 0)
                    {
                        Output.WriteLine("\t\t<span id=\"printbuttonitem\" class=\"action-sf-menu-item\" onclick=\"print_form_open();\"><img src=\"" + Static_Resources.Printer_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"printbuttonspan\">" + print_text + "</span></span>");
                    }
                    else
                    {
                        Output.WriteLine("\t\t<span id=\"printbuttonitem\" class=\"action-sf-menu-item\" onclick=\"window.print();return false;\"><img src=\"" + Static_Resources.Printer_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"printbuttonspan\">" + print_text + "</span></span>");
                    }

                    if ( isLoggedOn )
                    {
                        Output.WriteLine("\t\t<span id=\"sendbuttonitem\" class=\"action-sf-menu-item\" onclick=\"email_form_open();\"><img src=\"" + Static_Resources.Email_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"sendbuttonspan\">" + send_text + "</span></span>");

                        if (RequestSpecificValues.Current_Item.Web.ItemID > 0)
                        {
                            if (RequestSpecificValues.Current_User.Is_In_Bookshelf(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.VID))
                            {
                                Output.WriteLine("\t\t<span id=\"addbuttonitem\" class=\"action-sf-menu-item\" onclick=\"return remove_item_itemviewer();\"><img src=\"" + Static_Resources.Minussign_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"addbuttonspan\">" + remove_text + "</span></span>");
                            }
                            else
                            {
                                Output.WriteLine("\t\t<span id=\"addbuttonitem\" class=\"action-sf-menu-item\" onclick=\"add_item_form_open();return false;\"><img src=\"" + Static_Resources.Plussign_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"addbuttonspan\">" + add_text + "</span></span>");
                            }
                        }
                    }
                    else
                    {
                        Output.WriteLine("\t\t<span id=\"sendbuttonitem\" class=\"action-sf-menu-item\" onclick=\"window.location='" + logOnUrl + "';return false;\"><img src=\"" + Static_Resources.Email_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"sendbuttonspan\">" + send_text + "</span></span>");

                        if (RequestSpecificValues.Current_Item.Web.ItemID > 0)
                            Output.WriteLine("\t\t<span id=\"addbuttonitem\" class=\"action-sf-menu-item\" onclick=\"window.location='" + logOnUrl + "';return false;\"><img src=\"" + Static_Resources.Plussign_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"addbuttonspan\">" + add_text + "</span></span>");
                    }

                    Output.WriteLine("\t\t<span id=\"sharebuttonitem\" class=\"action-sf-menu-item\" onclick=\"toggle_share_form('share_button');\"><span id=\"sharebuttonspan\">Share</span></span>");

                    Output.WriteLine("\t</div>");
                    Output.WriteLine();
                }

                Output.WriteLine("\t<ul class=\"sf-menu\" id=\"sbkIhs_Menu\">");

                // Save the current view type
                ushort page = RequestSpecificValues.Current_Mode.Page.HasValue ? RequestSpecificValues.Current_Mode.Page.Value  : (ushort) 1;
                ushort subpage = RequestSpecificValues.Current_Mode.SubPage.HasValue ? RequestSpecificValues.Current_Mode.SubPage.Value : (ushort) 1;
                string viewerCode = RequestSpecificValues.Current_Mode.ViewerCode;
                RequestSpecificValues.Current_Mode.SubPage = 0;

                // Add any PRE-MENU instance options
                string first_pre_menu_option = String.Empty;
                string second_pre_menu_option = String.Empty;
                string third_pre_menu_option = String.Empty;
                if (UI_ApplicationCache_Gateway.Settings.Additional_Settings.ContainsKey("Item Viewer.Static First Menu Item"))
                    first_pre_menu_option = UI_ApplicationCache_Gateway.Settings.Additional_Settings["Item Viewer.Static First Menu Item"];
                if (UI_ApplicationCache_Gateway.Settings.Additional_Settings.ContainsKey("Item Viewer.Static Second Menu Item"))
                    second_pre_menu_option = UI_ApplicationCache_Gateway.Settings.Additional_Settings["Item Viewer.Static Second Menu Item"];
                if (UI_ApplicationCache_Gateway.Settings.Additional_Settings.ContainsKey("Item Viewer.Static Third Menu Item"))
                    third_pre_menu_option = UI_ApplicationCache_Gateway.Settings.Additional_Settings["Item Viewer.Static Third Menu Item"];
                if ((first_pre_menu_option.Length > 0) || (second_pre_menu_option.Length > 0) || ( third_pre_menu_option.Length > 0 ))
                {
                    if (first_pre_menu_option.Length > 0)
                    {
                        string[] first_splitter = first_pre_menu_option.Replace("[", "").Replace("]", "").Split(";".ToCharArray());
                        if (first_splitter.Length > 0)
                        {
                            Output.WriteLine("\t\t<li><a href=\"" + first_splitter[1] + "\" title=\"" + HttpUtility.HtmlEncode(first_splitter[0]) + "\">" + HttpUtility.HtmlEncode(first_splitter[0]) + "</a></li>");
                        }
                    }
                    if (second_pre_menu_option.Length > 0)
                    {
                        string[] second_splitter = second_pre_menu_option.Replace("[", "").Replace("]", "").Split(";".ToCharArray());
                        if (second_splitter.Length > 0)
                        {
                            Output.WriteLine("\t\t<li><a href=\"" + second_splitter[1] + "\" title=\"" + HttpUtility.HtmlEncode(second_splitter[0]) + "\">" + HttpUtility.HtmlEncode(second_splitter[0]) + "</a></li>");
                        }
                    }
                    if (third_pre_menu_option.Length > 0)
                    {
                        string[] third_splitter = third_pre_menu_option.Replace("[", "").Replace("]", "").Split(";".ToCharArray());
                        if (third_splitter.Length > 0)
                        {
                            Output.WriteLine("\t\t<li><a href=\"" + third_splitter[1] + "\" title=\"" + HttpUtility.HtmlEncode(third_splitter[0]) + "\">" + HttpUtility.HtmlEncode(third_splitter[0]) + "</a></li>");
                        }
                    }
                }

                // Add the item level views
                foreach (View_Object thisView in RequestSpecificValues.Current_Item.Behaviors.Views)
                {
                    if (((!itemRestrictedFromUserByIp) && (!RequestSpecificValues.Current_Item.Behaviors.Dark_Flag)) || (thisView.View_Type == View_Enum.CITATION) ||
                        (thisView.View_Type == View_Enum.ALL_VOLUMES) ||
                        (thisView.View_Type == View_Enum.RELATED_IMAGES))
                    {
                        // Special code for the CITATION view (TEMPORARY - v.3.2)
                        if (thisView.View_Type == View_Enum.CITATION)
                        {
                            if (RequestSpecificValues.Current_Mode.Is_Robot)
                            {
                                Output.Write("\t\t<li class=\"selected-sf-menu-item-link\"><a href=\"\">Description</a></li>");
                            }
                            else
                            {
                                RequestSpecificValues.Current_Mode.ViewerCode = "citation";
                                if (RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.EAD)
                                    RequestSpecificValues.Current_Mode.ViewerCode = "description";
                                if ((viewerCode == "citation") || (viewerCode == "marc") || (viewerCode == "metadata") ||
                                    (viewerCode == "usage") || (viewerCode == "description"))
                                {
                                    Output.Write("\t\t<li class=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Description</a>");
                                }
                                else
                                {
                                    Output.Write("\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Description</a>");
                                }
                                Output.WriteLine("<ul>");

                                if (RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.EAD)
                                    Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Archival Description</a></li>");
                                else
                                    Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Standard View</a></li>");

                                RequestSpecificValues.Current_Mode.ViewerCode = "marc";
                                Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">MARC View</a></li>");

                                RequestSpecificValues.Current_Mode.ViewerCode = "metadata";
                                Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Metadata</a></li>");

                                RequestSpecificValues.Current_Mode.ViewerCode = "usage";
                                Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Usage Statistics</a></li>");

                                Output.WriteLine("\t\t</ul></li>");
                                RequestSpecificValues.Current_Mode.ViewerCode = viewerCode;
                            }
                        }
                        else if (thisView.View_Type == View_Enum.ALL_VOLUMES)
                        {
                            string resource_type_upper = RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type_String.ToUpper();
                            string all_volumes = "All Volumes";
                            if (resource_type_upper.IndexOf("NEWSPAPER") >= 0)
                            {
                                all_volumes = "All Issues";
                            }
                            else if (resource_type_upper.IndexOf("MAP") >= 0)
                            {
                                all_volumes = "Related Maps";
                            }
                            else if (resource_type_upper.IndexOf("AERIAL") >= 0)
                            {
                                all_volumes = "Related Flights";
                            }

                            if (RequestSpecificValues.Current_Mode.Is_Robot)
                            {
                                Output.Write("\t\t<li><a href=\"" + UI_ApplicationCache_Gateway.Settings.Servers.Base_URL + "\\" + RequestSpecificValues.Current_Item.BibID + "\">" + all_volumes + "</a></li>");
                            }
                            else
                            {

                                RequestSpecificValues.Current_Mode.ViewerCode = "allvolumes";
                                if ((viewerCode == "allvolumes") || (viewerCode == "allvolumes2") ||
                                    (viewerCode == "allvolumes3"))
                                {
                                    Output.Write("\t\t<li class=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + all_volumes + "</a>");
                                }
                                else
                                {
                                    Output.Write("\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + all_volumes + "</a>");
                                }
                                Output.WriteLine("<ul>");

                                RequestSpecificValues.Current_Mode.ViewerCode = "allvolumes";
                                Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Tree View</a></li>");

                                RequestSpecificValues.Current_Mode.ViewerCode = "allvolumes2";
                                Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Thumbnails</a></li>");

                                if ((RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.LoggedOn) && (RequestSpecificValues.Current_User.Is_Internal_User))
                                {
                                    RequestSpecificValues.Current_Mode.ViewerCode = "allvolumes3";
                                    Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">List View</a></li>");
                                }

                                Output.WriteLine("\t\t</ul></li>");
                                RequestSpecificValues.Current_Mode.ViewerCode = viewerCode;
                            }
                        }
                        else
                        {
                            List<string> item_nav_bar_link = Item_Nav_Bar_HTML_Factory.Get_Nav_Bar_HTML(thisView, RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type_String, RequestSpecificValues.HTML_Skin.Base_Skin_Code, RequestSpecificValues.Current_Mode, -1, UI_ApplicationCache_Gateway.Translation, showZoomable, RequestSpecificValues.Current_Item);

                            // Add each nav bar link
                            foreach (string this_link in item_nav_bar_link)
                            {
                                Output.WriteLine("\t\t" + this_link + "");
                            }
                        }
                    }
                }

                // If this is citation or index mode, the number may be an invalid page sequence
                if ((page <= 0) ||
                    (RequestSpecificValues.Current_Mode.ViewerCode == View_Object.Viewer_Code_By_Type(View_Enum.RELATED_IMAGES)[0]))
                {
                    RequestSpecificValues.Current_Mode.Page = 1;
                }

                if ((RequestSpecificValues.Current_Item.Web.Static_PageCount > 0) && (RequestSpecificValues.Current_Page == null))
                {
                    RequestSpecificValues.Current_Page = RequestSpecificValues.Current_Item.Web.Pages_By_Sequence[0];
                }

                // Add each page display type
                if ((RequestSpecificValues.Current_Page != null) && (!itemRestrictedFromUserByIp))
                {
                    int page_seq = RequestSpecificValues.Current_Mode.Page.HasValue ? RequestSpecificValues.Current_Mode.Page.Value  : 1;
                    string resourceType = RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type_String.ToUpper();
                    if (RequestSpecificValues.Current_Item.Behaviors.Item_Level_Page_Views_Count > 0)
                    {
                        List<string> pageViewLinks = new List<string>();

                        foreach (View_Object thisPageView in RequestSpecificValues.Current_Item.Behaviors.Item_Level_Page_Views)
                        {
                            View_Enum thisViewType = thisPageView.View_Type;
                            foreach (SobekCM_File_Info thisFile in RequestSpecificValues.Current_Page.Files)
                            {
                                View_Object fileObject = thisFile.Get_Viewer();
                                if ((fileObject != null) && (fileObject.View_Type == thisViewType))
                                {
                                    pageViewLinks.AddRange(Item_Nav_Bar_HTML_Factory.Get_Nav_Bar_HTML(thisFile.Get_Viewer(), resourceType, RequestSpecificValues.HTML_Skin.Base_Skin_Code, RequestSpecificValues.Current_Mode, page_seq, UI_ApplicationCache_Gateway.Translation, showZoomable, RequestSpecificValues.Current_Item));
                                }
                            }
                        }

                        if (RequestSpecificValues.Current_Item.BibID == "UF00001672")
                        {
                            string filename = RequestSpecificValues.Current_Page.Files[0].File_Name_Sans_Extension + ".txt";
                            SobekCM_File_Info newFile = new SobekCM_File_Info(filename);
                            pageViewLinks.AddRange(Item_Nav_Bar_HTML_Factory.Get_Nav_Bar_HTML(newFile.Get_Viewer(), resourceType, RequestSpecificValues.HTML_Skin.Base_Skin_Code, RequestSpecificValues.Current_Mode, page_seq, UI_ApplicationCache_Gateway.Translation, showZoomable, RequestSpecificValues.Current_Item));
                        }

                        // Only continue if there were views
                        if (pageViewLinks.Count > 0)
                        {
                            // Determine the name for this menu item
                            string menu_title = "Page Image";
                            if (resourceType.IndexOf("MAP") >= 0)
                            {
                                menu_title = "Map Image";
                            }
                            else if ((resourceType.IndexOf("AERIAL") >= 0) || (resourceType.IndexOf("PHOTOGRAPH") >= 0))
                            {
                                menu_title = "Image";
                            }
                            if (RequestSpecificValues.Current_Item.Web.Static_PageCount > 1)
                                menu_title = menu_title + "s";

                            // Get the link for the first page view
                            string link = pageViewLinks[0].Substring(pageViewLinks[0].IndexOf("href=\"") + 6);
                            link = link.Substring(0, link.IndexOf("\""));

                            // Was this a match?
                            if ((RequestSpecificValues.Current_Mode.ViewerCode == page_seq + "t") || (RequestSpecificValues.Current_Mode.ViewerCode == page_seq + "x") || (RequestSpecificValues.Current_Mode.ViewerCode == page_seq + "j"))
                            {
                                Output.Write("\t\t<li class=\"selected-sf-menu-item-link\"><a href=\"" + link + "\">" + menu_title + "</a>");
                            }
                            else
                            {
                                Output.Write("\t\t<li><a href=\"" + link + "\">" + menu_title + "</a>");
                            }
                            Output.WriteLine("<ul>");

                            foreach (string pageLink in pageViewLinks)
                            {
                                Output.WriteLine("\t\t\t<li>" + pageLink + "</li>");
                            }

                            Output.WriteLine("\t\t</ul></li>");
                        }
                    }
                }

                if (itemRestrictedFromUserByIp)
                {
                    List<string> restricted_nav_bar_link = Item_Nav_Bar_HTML_Factory.Get_Nav_Bar_HTML(new View_Object(View_Enum.RESTRICTED), RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type_String.ToUpper(), RequestSpecificValues.HTML_Skin.Base_Skin_Code, RequestSpecificValues.Current_Mode, 0, UI_ApplicationCache_Gateway.Translation, showZoomable, RequestSpecificValues.Current_Item);
                    Output.WriteLine("\t\t" + restricted_nav_bar_link[0] + "");
                }

                // Add the MANAGE button?
                if (userCanEditItem)
                {
                    // Get the MANAGE URL (which is actually an item view)
                    RequestSpecificValues.Current_Mode.ViewerCode = "manage";
                    string manage_menu_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);

                    if (RequestSpecificValues.Current_Item.METS_Header.RecordStatus_Enum != METS_Record_Status.BIB_LEVEL)
                    {

                        // Get all the mySObek URLs
                        RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.My_Sobek;
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Item_Metadata;
                        string edit_metadata_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Item_Behaviors;
                        string edit_behaviors_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Page_Images_Management;
                        string page_images_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.File_Management;
                        string manage_downloads = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);

                        RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Item_Display;

                        Output.WriteLine("\t\t<li><a href=\"" + manage_menu_url + "\">Manage</a><ul>");

                        Output.WriteLine("\t\t\t<li><a href=\"" + edit_metadata_url + "\">Edit Metadata</a></li>");
                        Output.WriteLine("\t\t\t<li><a href=\"" + edit_behaviors_url + "\">Edit Item Behaviors</a></li>");
                        Output.WriteLine("\t\t\t<li><a href=\"" + manage_downloads + "\">Manage Download Files</a></li>");

                        if (RequestSpecificValues.Current_Item.Web.Static_PageCount == 0)
                            Output.WriteLine("\t\t\t<li><a href=\"" + page_images_url + "\">Manage Pages and Divisions</a></li>");
                        else
                        {
                            RequestSpecificValues.Current_Mode.ViewerCode = "qc";
                            Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Manage Pages and Divisions</a></li>");
                        }

                        RequestSpecificValues.Current_Mode.ViewerCode = "mapedit";
                        Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">Manage Geo-Spatial Data (beta)</a></li>");

                        RequestSpecificValues.Current_Mode.ViewerCode = "ts";
                        Output.WriteLine("\t\t\t<li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">View Tracking Sheet</a></li>");

                        Output.WriteLine("\t\t</ul></li>");
                    }
                    else
                    {
                        // Get all the mySObek URLs
                        RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.My_Sobek;
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Group_Behaviors;
                        string edit_behaviors_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Group_Add_Volume;
                        string add_volume_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Group_Mass_Update_Items;
                        string mass_update_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);

                        RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Item_Display;

                        Output.WriteLine("\t\t<li><a href=\"" + manage_menu_url + "\">Manage</a><ul>");

                        Output.WriteLine("\t\t\t<li><a href=\"" + edit_behaviors_url + "\">Edit Item Group Behaviors</a></li>");
                        Output.WriteLine("\t\t\t<li><a href=\"" + add_volume_url + "\">Add New Volume</a></li>");
                        Output.WriteLine("\t\t\t<li><a href=\"" + mass_update_url + "\">Mass Update Item Behaviors</a></li>");

                        Output.WriteLine("\t\t</ul></li>");
                    }
                }

                // Set current submode back
                RequestSpecificValues.Current_Mode.Page = page;
                RequestSpecificValues.Current_Mode.ViewerCode = viewerCode;
                RequestSpecificValues.Current_Mode.SubPage = subpage;

                Output.WriteLine("\t</ul>");
                Output.WriteLine("</nav>");
                Output.WriteLine();

                Output.WriteLine("<!-- Initialize the main item menu -->");
                Output.WriteLine("<script>");
                Output.WriteLine("\tjQuery(document).ready(function () { jQuery('ul.sf-menu').superfish(); });");
                Output.WriteLine("</script>");
                Output.WriteLine();
            }

            return true;
        }
        private bool complete_item_submission(SobekCM_Item Item_To_Complete,  Custom_Tracer Tracer )
        {
            // Set an initial flag
            criticalErrorEncountered = false;
            bool xml_found = false;

            string[] all_files = Directory.GetFiles(userInProcessDirectory);
            SortedList<string, List<string>> image_files = new SortedList<string, List<string>>();
            SortedList<string, List<string>> download_files = new SortedList<string, List<string>>();
            foreach (string thisFile in all_files)
            {
                FileInfo thisFileInfo = new FileInfo(thisFile);

                if ((thisFileInfo.Name.IndexOf("agreement.txt") != 0) && (thisFileInfo.Name.IndexOf("TEMP000001_00001.mets") != 0) && (thisFileInfo.Name.IndexOf("doc.xml") != 0) && (thisFileInfo.Name.IndexOf("ufdc_mets.xml") != 0) && (thisFileInfo.Name.IndexOf("marc.xml") != 0))
                {
                    // Get information about this files name and extension
                    string extension_upper = thisFileInfo.Extension.ToUpper();
                    string filename_sans_extension = thisFileInfo.Name.Replace(thisFileInfo.Extension, "");
                    string name_upper = thisFileInfo.Name.ToUpper();

                    // Is this a page image?
                    if ((extension_upper == ".JPG") || (extension_upper == ".TIF") || (extension_upper == ".JP2") || (extension_upper == ".JPX"))
                    {
                        // Exclude .QC.jpg files
                        if (name_upper.IndexOf(".QC.JPG") < 0)
                        {
                            // If this is a thumbnail, trim off the THM part on the file name
                            if (name_upper.IndexOf("THM.JPG") > 0)
                            {
                                filename_sans_extension = filename_sans_extension.Substring(0, filename_sans_extension.Length - 3);
                            }

                            // Is this the first image file with this name?
                            if (image_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                image_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List<string> newImageGrouping = new List<string> {thisFileInfo.Name};
                                image_files[filename_sans_extension.ToLower()] = newImageGrouping;
                            }
                        }
                    }
                    else
                    {
                        // If this does not match the exclusion regular expression, than add this
                        if (!Regex.Match(thisFileInfo.Name, UI_ApplicationCache_Gateway.Settings.Resources.Files_To_Exclude_From_Downloads, RegexOptions.IgnoreCase).Success)
                        {
                            // Also, exclude files that are .XML and marc.xml, or doc.xml, or have the bibid in the name
                            if ((thisFileInfo.Name.IndexOf("marc.xml", StringComparison.OrdinalIgnoreCase) != 0) && (thisFileInfo.Name.IndexOf("marc.xml", StringComparison.OrdinalIgnoreCase) != 0) && (thisFileInfo.Name.IndexOf(".mets", StringComparison.OrdinalIgnoreCase) < 0))
                            {
                                // Is this the first image file with this name?
                                if (download_files.ContainsKey(filename_sans_extension.ToLower()))
                                {
                                    download_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                                }
                                else
                                {
                                    List<string> newDownloadGrouping = new List<string> {thisFileInfo.Name};
                                    download_files[filename_sans_extension.ToLower()] = newDownloadGrouping;
                                }

                                if (thisFileInfo.Name.IndexOf(".xml", StringComparison.OrdinalIgnoreCase) > 0)
                                    xml_found = true;
                            }
                        }
                    }
                }
            }

            // This package is good to go, so build it, save, etc...
            try
            {
                // Save the METS file to the database and back to the directory
                Item_To_Complete.Source_Directory = userInProcessDirectory;

                // Step through and add each file
                Item_To_Complete.Divisions.Download_Tree.Clear();
                if ((completeTemplate.Upload_Types == CompleteTemplate.Template_Upload_Types.File_or_URL) || (completeTemplate.Upload_Types == CompleteTemplate.Template_Upload_Types.File))
                {
                    // Step through each file

                    bool error_reading_file_occurred = false;

                    // Add the image files first
                    bool jpeg_added = false;
                    bool jp2_added = false;
                    foreach(string thisFileKey in image_files.Keys )
                    {
                        // Get the list of files
                        List<string> theseFiles = image_files[thisFileKey];

                        // Add each file
                        foreach (string thisFile in theseFiles)
                        {
                            // Create the new file object and compute a label
                            FileInfo fileInfo = new FileInfo(thisFile);
                            SobekCM_File_Info newFile = new SobekCM_File_Info(fileInfo.Name);
                            string label = fileInfo.Name.Replace(fileInfo.Extension, "");
                            if (HttpContext.Current.Session["file_" + thisFileKey] != null)
                            {
                                string possible_label = HttpContext.Current.Session["file_" + thisFileKey].ToString();
                                if (possible_label.Length > 0)
                                    label = possible_label;
                            }

                            // Add this file
                            Item_To_Complete.Divisions.Physical_Tree.Add_File(newFile, label);

                            // Seperate code for JP2 and JPEG type files
                            string extension = fileInfo.Extension.ToUpper();
                            if (extension.IndexOf("JP2") >= 0)
                            {
                                if (!error_reading_file_occurred)
                                {
                                    if (!newFile.Compute_Jpeg2000_Attributes(userInProcessDirectory))
                                        error_reading_file_occurred = true;
                                }
                                jp2_added = true;
                            }
                            else
                            {
                                if (!error_reading_file_occurred)
                                {
                                    if (!newFile.Compute_Jpeg_Attributes(userInProcessDirectory))
                                        error_reading_file_occurred = true;
                                }
                                jpeg_added = true;
                            }
                        }
                    }

                    // Add the download files next
                    foreach(string thisFileKey in download_files.Keys )
                    {
                        // Get the list of files
                        List<string> theseFiles = download_files[thisFileKey];

                        // Add each file
                        foreach (string thisFile in theseFiles)
                        {
                            // Create the new file object and compute a label
                            FileInfo fileInfo = new FileInfo(thisFile);
                            SobekCM_File_Info newFile = new SobekCM_File_Info(fileInfo.Name);
                            string label = fileInfo.Name.Replace( fileInfo.Extension, "");
                            if (HttpContext.Current.Session["file_" + thisFileKey] != null)
                            {
                                string possible_label = HttpContext.Current.Session["file_" + thisFileKey].ToString();
                                if (possible_label.Length > 0)
                                    label = possible_label;
                            }

                            // Add this file
                            Item_To_Complete.Divisions.Download_Tree.Add_File(newFile, label);
                        }
                    }

                    // Add the JPEG2000 and JPEG-specific viewers
                    Item_To_Complete.Behaviors.Clear_Views();
                    if (jpeg_added)
                    {
                        Item_To_Complete.Behaviors.Add_View(View_Enum.JPEG);
                    }
                    if (jp2_added)
                    {
                        Item_To_Complete.Behaviors.Add_View(View_Enum.JPEG2000);
                    }
                }

                // Determine the total size of the package before saving
                string[] all_files_final = Directory.GetFiles(userInProcessDirectory);
                double size = all_files_final.Aggregate<string, double>(0, (Current, ThisFile) => Current + (((new FileInfo(ThisFile)).Length)/1024));
                Item_To_Complete.DiskSize_KB = size;

                // BibID and VID will be automatically assigned
                Item_To_Complete.BibID = completeTemplate.BibID_Root;
                Item_To_Complete.VID = String.Empty;

                // Set some values in the tracking portion
                if (Item_To_Complete.Divisions.Files.Count > 0)
                {
                    Item_To_Complete.Tracking.Born_Digital = true;
                }
                Item_To_Complete.Tracking.VID_Source = "SobekCM:" + templateCode;

                // If this is a dataset and XML file was uploaded, add some viewers
                if ((xml_found) && (Item_To_Complete.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.Dataset))
                {
                    Item_To_Complete.Behaviors.Add_View(View_Enum.DATASET_CODEBOOK);
                    Item_To_Complete.Behaviors.Add_View(View_Enum.DATASET_REPORTS);
                    Item_To_Complete.Behaviors.Add_View(View_Enum.DATASET_VIEWDATA);
                }

                // Save to the database
                try
                {
                    Resource_Object.Database.SobekCM_Database.Save_New_Digital_Resource(Item_To_Complete, false, true, RequestSpecificValues.Current_User.UserName, String.Empty, RequestSpecificValues.Current_User.UserID);
                }
                catch (Exception ee)
                {
                    StreamWriter writer = new StreamWriter(userInProcessDirectory + "\\exception.txt", false);
                    writer.WriteLine( "ERROR CAUGHT WHILE SAVING NEW DIGITAL RESOURCE");
                    writer.WriteLine( DateTime.Now.ToString());
                    writer.WriteLine();
                    writer.WriteLine( ee.Message );
                    writer.WriteLine( ee.StackTrace );
                    writer.Flush();
                    writer.Close();
                    throw;
                }

                // Assign the file root and assoc file path
                Item_To_Complete.Web.File_Root = Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8, 2);
                Item_To_Complete.Web.AssocFilePath = Item_To_Complete.Web.File_Root + "\\" + Item_To_Complete.VID + "\\";

                // Create the static html pages
                string base_url = RequestSpecificValues.Current_Mode.Base_URL;
                try
                {
                    Static_Pages_Builder staticBuilder = new Static_Pages_Builder(UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL, UI_ApplicationCache_Gateway.Settings.Servers.Base_Data_Directory, RequestSpecificValues.HTML_Skin.Skin_Code);
                    string filename = userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html";
                    staticBuilder.Create_Item_Citation_HTML(Item_To_Complete, filename, String.Empty);

                    // Copy the static HTML file to the web server
                    try
                    {
                        if (!Directory.Exists(UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + item.BibID.Substring(0, 2) + "\\" + item.BibID.Substring(2, 2) + "\\" + item.BibID.Substring(4, 2) + "\\" + item.BibID.Substring(6, 2) + "\\" + item.BibID.Substring(8)))
                            Directory.CreateDirectory(UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + item.BibID.Substring(0, 2) + "\\" + item.BibID.Substring(2, 2) + "\\" + item.BibID.Substring(4, 2) + "\\" + item.BibID.Substring(6, 2) + "\\" + item.BibID.Substring(8));
                        if (File.Exists(userInProcessDirectory + "\\" + item.BibID + "_" + item.VID + ".html"))
                            File.Copy(userInProcessDirectory + "\\" + item.BibID + "_" + item.VID + ".html", UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + item.BibID.Substring(0, 2) + "\\" + item.BibID.Substring(2, 2) + "\\" + item.BibID.Substring(4, 2) + "\\" + item.BibID.Substring(6, 2) + "\\" + item.BibID.Substring(8) + "\\" + item.BibID + "_" + item.VID + ".html", true);
                    }
                    catch (Exception)
                    {
                        // This is not critical
                    }
                }
                catch (Exception)
                {
                    // An error here is not catastrophic
                }

                RequestSpecificValues.Current_Mode.Base_URL = base_url;

                // Save the rest of the metadata
                Item_To_Complete.Save_SobekCM_METS();

                // Add this to the cache
                UI_ApplicationCache_Gateway.Items.Add_SobekCM_Item(Item_To_Complete);

                // Create the options dictionary used when saving information to the database, or writing MarcXML
                Dictionary<string, object> options = new Dictionary<string, object>();
                if (UI_ApplicationCache_Gateway.Settings.MarcGeneration != null)
                {
                    options["MarcXML_File_ReaderWriter:MARC Cataloging Source Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Cataloging_Source_Code;
                    options["MarcXML_File_ReaderWriter:MARC Location Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Location_Code;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Agency"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Agency;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Place"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Place;
                    options["MarcXML_File_ReaderWriter:MARC XSLT File"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.XSLT_File;
                }
                options["MarcXML_File_ReaderWriter:System Name"] = UI_ApplicationCache_Gateway.Settings.System.System_Name;
                options["MarcXML_File_ReaderWriter:System Abbreviation"] = UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation;

                // Save the marc xml file
                MarcXML_File_ReaderWriter marcWriter = new MarcXML_File_ReaderWriter();
                string errorMessage;
                marcWriter.Write_Metadata(Item_To_Complete.Source_Directory + "\\marc.xml", Item_To_Complete, options, out errorMessage);

                // Delete the TEMP mets file
                if (File.Exists(userInProcessDirectory + "\\TEMP000001_00001.mets"))
                    File.Delete(userInProcessDirectory + "\\TEMP000001_00001.mets");

                // Rename the METS file to the XML file
                if ((!File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets.xml")) &&
                    (File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets")))
                {
                    File.Move(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets", userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets.xml");
                }

                string serverNetworkFolder = UI_ApplicationCache_Gateway.Settings.Servers.Image_Server_Network + Item_To_Complete.Web.AssocFilePath;

                // Create the folder
                if (!Directory.Exists(serverNetworkFolder))
                    Directory.CreateDirectory(serverNetworkFolder);
                if (!Directory.Exists(serverNetworkFolder + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name))
                    Directory.CreateDirectory(serverNetworkFolder + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name);

                // Copy the static HTML page over first
                if (File.Exists(userInProcessDirectory + "\\" + item.BibID + "_" + item.VID + ".html"))
                {
                    File.Copy(userInProcessDirectory + "\\" + item.BibID + "_" + item.VID + ".html", serverNetworkFolder + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name + "\\" + item.BibID + "_" + item.VID + ".html", true);
                    File.Delete(userInProcessDirectory + "\\" + item.BibID + "_" + item.VID + ".html");
                }

                // Copy all the files
                string[] allFiles = Directory.GetFiles(userInProcessDirectory);
                foreach (string thisFile in allFiles)
                {
                    string destination_file = serverNetworkFolder + "\\" + (new FileInfo(thisFile)).Name;
                    File.Copy(thisFile, destination_file, true);
                }

                // Add this to the cache
                UI_ApplicationCache_Gateway.Items.Add_SobekCM_Item(Item_To_Complete);

                // Incrememnt the count of number of items submitted by this RequestSpecificValues.Current_User
                RequestSpecificValues.Current_User.Items_Submitted_Count++;
                if (!RequestSpecificValues.Current_User.BibIDs.Contains(Item_To_Complete.BibID))
                    RequestSpecificValues.Current_User.Add_BibID(Item_To_Complete.BibID);

                // Now, delete all the files here
                all_files = Directory.GetFiles(userInProcessDirectory);
                foreach (string thisFile in all_files)
                {
                    File.Delete(thisFile);
                }

                // Finally, set the item for more processing if there were any files
                if (((image_files.Count > 0) || (download_files.Count > 0)) && ( Item_To_Complete.Web.ItemID > 0 ))
                {
                    SobekCM_Database.Update_Additional_Work_Needed_Flag(Item_To_Complete.Web.ItemID, true, Tracer);
                }

                // Clear any temporarily assigned current project and CompleteTemplate
                RequestSpecificValues.Current_User.Current_Default_Metadata = null;
                RequestSpecificValues.Current_User.Current_Template = null;

            }
            catch (Exception ee)
            {
                validationErrors.Add("Error encountered during item save!");
                validationErrors.Add(ee.ToString().Replace("\r", "<br />"));

                // Set an initial flag
                criticalErrorEncountered = true;

                string error_body = "<strong>ERROR ENCOUNTERED DURING ONLINE SUBMITTAL PROCESS</strong><br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a><br />User: "******"<br /><br /></blockquote>" + ee.ToString().Replace("\n", "<br />");
                string error_subject = "Error during submission for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                string email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Error_Email;
                if (email_to.Length == 0)
                    email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Email;
                Email_Helper.SendEmail(email_to, error_subject, error_body, true, RequestSpecificValues.Current_Mode.Instance_Name);
            }

            if (!criticalErrorEncountered)
            {
                // Send email to the email from the CompleteTemplate, if one was provided
                if (completeTemplate.Email_Upon_Receipt.Length > 0)
                {
                    string body = "New item submission complete!<br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Submittor: " + RequestSpecificValues.Current_User.Full_Name + " ( " + RequestSpecificValues.Current_User.Email + " )<br />Link: <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + Item_To_Complete.BibID + ":" + Item_To_Complete.VID + "</a></blockquote>";
                    string subject = "Item submission complete for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                    Email_Helper.SendEmail(completeTemplate.Email_Upon_Receipt, subject, body, true, RequestSpecificValues.Current_Mode.Instance_Name);
                }

                // If the RequestSpecificValues.Current_User wants to have a message sent, send one
                if (RequestSpecificValues.Current_User.Send_Email_On_Submission)
                {
                    // Create the mail message
                    string body2 = "<strong>CONGRATULATIONS!</strong><br /><br />Your item has been successfully added to the digital library and will appear immediately.  Search indexes may take a couple minutes to build, at which time this item will be discoverable through the search interface. <br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a></blockquote>";
                    string subject2 = "Item submission complete for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                    Email_Helper.SendEmail(RequestSpecificValues.Current_User.Email, subject2, body2, true, RequestSpecificValues.Current_Mode.Instance_Name);
                }

                // Also clear any searches or browses ( in the future could refine this to only remove those
                // that are impacted by this save... but this is good enough for now )
                CachedDataManager.Clear_Search_Results_Browses();
            }

            return criticalErrorEncountered;
        }
        private void recurse_through_nodes( SobekCM_Item ThisPackage, abstract_TreeNode Node, List<Page_TreeNode> PagesEncountered )
        {
            if (Node.Page)
            {
                Page_TreeNode pageNode = (Page_TreeNode)Node;
                if ( !PagesEncountered.Contains( pageNode ))
                {
                    pageseq++;

                    // Add each of the files view codes to the list
                    bool page_added = false;
                    foreach (SobekCM_File_Info thisFile in pageNode.Files)
                    {
                        string upper_name = thisFile.System_Name.ToUpper();
                        if ((upper_name.IndexOf("SOUNDFILESONLY") < 0) && ( upper_name.IndexOf("FILMONLY") < 0 ) && ( upper_name.IndexOf("MULTIMEDIA") < 0 ) && ( upper_name.IndexOf("THM.JPG") < 0 ))
                        {
                            if (!page_added)
                            {
                                // Add this to the simple page collection
                                ThisPackage.Web.Add_Pages_By_Sequence(pageNode);
                                PagesEncountered.Add(pageNode);
                                page_added = true;
                            }
                            View_Object thisViewer = thisFile.Get_Viewer();
                            if (thisViewer != null)
                            {
                                string[] codes = thisViewer.Viewer_Codes;
                                if ((codes.Length > 0) && (codes[0].Length > 0))
                                {
                                    ThisPackage.Web.Viewer_To_File[pageseq.ToString() + codes[0]] = thisFile;
                                }
                            }
                        }

                        // TEST: Special case for text
                        if ((ThisPackage.BibID == "UF00001672") || ( ThisPackage.BibID == "TEST000003"))
                        {
                            if (thisFile.File_Extension.ToLower().IndexOf("jpg") >= 0)
                            {
                                string filename = thisFile.File_Name_Sans_Extension + ".txt";
                                SobekCM_File_Info thisFileInfo = new SobekCM_File_Info(filename);
                                ThisPackage.Web.Viewer_To_File[pageseq.ToString() + "t"] = thisFileInfo;
                            }
                        }
                    }
                }
            }
            else
            {
                divseq++;
                Division_TreeNode divNode = (Division_TreeNode)Node;
                foreach (abstract_TreeNode childNode in divNode.Nodes)
                {
                    recurse_through_nodes(ThisPackage, childNode, PagesEncountered);
                }
            }
        }
        private void read_file_sec(XmlReader R, bool Minimize_File_Info, Dictionary<string, SobekCM_File_Info> FilesByFileid)
        {
            string checkSum = String.Empty;
            string checkSumType = String.Empty;
            string fileID = String.Empty;
            string size = String.Empty;

			// Only allow ONE instance of each file in the METS
	        Dictionary<string, SobekCM_File_Info> filename_to_object = new Dictionary<string, SobekCM_File_Info>();

            // begin to loop through the XML DOM tree

            // Loop through reading each XML node
            do
            {
                // get the right division information based on node type
                switch (R.NodeType)
                {
                    case XmlNodeType.EndElement:
                        if ((R.Name == "METS:fileSec") || (R.Name == "fileSec"))
                        {
                            return;
                        }
                        break;

                    case XmlNodeType.Element:
                        if (((R.Name == "METS:file") || (R.Name == "file")) && (R.HasAttributes) && (R.MoveToAttribute("ID")))
                        {
                            fileID = R.Value;

                            if (R.MoveToAttribute("CHECKSUM"))
                            {
                                checkSum = R.Value;
                                checkSumType = R.MoveToAttribute("CHECKSUMTYPE") ? R.Value : String.Empty;
                            }
                            else
                            {
                                checkSum = String.Empty;
                                checkSumType = String.Empty;
                            }

                            size = R.MoveToAttribute("SIZE") ? R.Value : String.Empty;
                        }

                        if (((R.Name == "METS:FLocat") || (R.Name == "FLocat")) && (R.HasAttributes))
                        {
                            // Determine the location type ( System or URL )
                            SobekCM_File_Info_Type_Enum locType = SobekCM_File_Info_Type_Enum.SYSTEM;
                            if (R.MoveToAttribute("LOCTYPE"))
                            {
                                if ( R.Value == "URL")
                                    locType = SobekCM_File_Info_Type_Enum.URL;
                            }

                            if (R.MoveToAttribute("xlink:href"))
                            {
                                // Get and clean up the system name
                                string systemName;
                                if ((locType == SobekCM_File_Info_Type_Enum.SYSTEM) && ( R.Value.IndexOf("http:") < 0 ))
                                    systemName = R.Value.Replace("%20", " ").Replace("/", "\\");
                                else
                                    systemName = R.Value.Replace("%20", " ");

	                            if (systemName.ToLower() != "web.config")
	                            {
	                                // Is this a new FILEID?
	                                SobekCM_File_Info newFile;
	                                if (!FilesByFileid.ContainsKey(fileID))
		                            {
										// In addition, is this a new FILENAME?
										if (filename_to_object.ContainsKey(systemName.ToUpper()))
										{
											newFile = filename_to_object[systemName.ToUpper()];
											FilesByFileid[fileID] = newFile;
										}
										else
										{
											newFile = new SobekCM_File_Info(systemName);
											FilesByFileid[fileID] = newFile;
											filename_to_object[systemName.ToUpper()] = newFile;
										}
		                            }
		                            else
		                            {
			                            newFile = FilesByFileid[fileID];
			                            // newFile.System_Name = systemName;  (SHOULD BE REDUNDANT - removed 5/2014)
		                            }

		                            if ((!Minimize_File_Info) && (!String.IsNullOrEmpty(checkSum)) && (!String.IsNullOrEmpty(checkSumType)))
		                            {
			                            newFile.Checksum = checkSum;
			                            newFile.Checksum_Type = checkSumType;
		                            }

		                            if (size.Length > 0)
		                            {
			                            try
			                            {
				                            newFile.Size = Convert.ToInt64(size);
			                            }
			                            catch
			                            {
			                            }
		                            }
	                            }
                            }
                        }
                        break;
                }
            } while (R.Read());
        }
        private void read_file_sec(XmlReader r, SobekCM_Item package, bool Minimize_File_Info, Dictionary<string, SobekCM_File_Info> files_by_fileid)
        {
            string systemName = String.Empty;
            string checkSum = String.Empty;
            string checkSumType = String.Empty;
            string fileID = String.Empty;
            string size = String.Empty;

            // begin to loop through the XML DOM tree
            SobekCM_File_Info newFile;

            // Loop through reading each XML node
            do
            {
                // get the right division information based on node type
                switch (r.NodeType)
                {
                    case XmlNodeType.EndElement:
                        if ((r.Name == "METS:fileSec") || (r.Name == "fileSec"))
                        {
                            return;
                        }
                        break;

                    case XmlNodeType.Element:
                        if (((r.Name == "METS:file") || (r.Name == "file")) && (r.HasAttributes) && (r.MoveToAttribute("ID")))
                        {
                            fileID = r.Value;

                            if (r.MoveToAttribute("CHECKSUM"))
                            {
                                checkSum = r.Value;
                                if (r.MoveToAttribute("CHECKSUMTYPE"))
                                    checkSumType = r.Value;
                                else
                                    checkSumType = String.Empty;
                            }
                            else
                            {
                                checkSum = String.Empty;
                                checkSumType = String.Empty;
                            }

                            if (r.MoveToAttribute("SIZE"))
                                size = r.Value;
                            else
                                size = String.Empty;
                        }

                        if (((r.Name == "METS:FLocat") || (r.Name == "FLocat")) && (r.HasAttributes))
                        {
                            if (r.MoveToAttribute("xlink:href"))
                            {
                                systemName = r.Value.Replace("%20", " ");
                                newFile = null;
                                if (!files_by_fileid.ContainsKey(fileID))
                                {
                                    newFile = new SobekCM_File_Info(systemName);
                                    files_by_fileid[fileID] = newFile;
                                }
                                else
                                {
                                    newFile = files_by_fileid[fileID];
                                    newFile.System_Name = systemName;
                                }

                                if ((!Minimize_File_Info) && (!String.IsNullOrEmpty(checkSum)) && (!String.IsNullOrEmpty(checkSumType)))
                                {
                                    newFile.Checksum = checkSum;
                                    newFile.Checksum_Type = checkSumType;
                                }

                                if (size.Length > 0)
                                {
                                    try
                                    {
                                        newFile.Size = Convert.ToInt64(size);
                                    }
                                    catch
                                    {
                                    }
                                }
                            }
                        }
                        break;
                }
            } while (r.Read());
        }
        private bool complete_item_submission(SobekCM_Item Item_To_Complete, Custom_Tracer Tracer)
        {
            // Set an initial flag
            criticalErrorEncountered = false;

            string[] all_files = Directory.GetFiles(digitalResourceDirectory);
            SortedList <string, List <string> > image_files    = new SortedList <string, List <string> >();
            SortedList <string, List <string> > download_files = new SortedList <string, List <string> >();

            foreach (string thisFile in all_files)
            {
                FileInfo thisFileInfo = new FileInfo(thisFile);

                if ((thisFileInfo.Name.IndexOf("agreement.txt") != 0) && (thisFileInfo.Name.IndexOf("TEMP000001_00001.mets") != 0) && (thisFileInfo.Name.IndexOf("doc.xml") != 0) && (thisFileInfo.Name.IndexOf("ufdc_mets.xml") != 0) && (thisFileInfo.Name.IndexOf("marc.xml") != 0))
                {
                    // Get information about this files name and extension
                    string extension_upper         = thisFileInfo.Extension.ToUpper();
                    string filename_sans_extension = thisFileInfo.Name.Replace(thisFileInfo.Extension, "");
                    string name_upper = thisFileInfo.Name.ToUpper();

                    // Is this a page image?
                    if ((extension_upper == ".JPG") || (extension_upper == ".TIF") || (extension_upper == ".JP2") || (extension_upper == ".JPX"))
                    {
                        // Exclude .QC.jpg files
                        if (name_upper.IndexOf(".QC.JPG") < 0)
                        {
                            // If this is a thumbnail, trim off the THM part on the file name
                            if (name_upper.IndexOf("THM.JPG") > 0)
                            {
                                filename_sans_extension = filename_sans_extension.Substring(0, filename_sans_extension.Length - 3);
                            }

                            // Is this the first image file with this name?
                            if (image_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                image_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List <string> newImageGrouping = new List <string> {
                                    thisFileInfo.Name
                                };
                                image_files[filename_sans_extension.ToLower()] = newImageGrouping;
                            }
                        }
                    }
                    else
                    {
                        // If this does not match the exclusion regular expression, than add this
                        if ((!Regex.Match(thisFileInfo.Name, SobekCM_Library_Settings.Files_To_Exclude_From_Downloads, RegexOptions.IgnoreCase).Success) && (String.Compare(thisFileInfo.Name, Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html", true) != 0))
                        {
                            // Is this the first image file with this name?
                            if (download_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                download_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List <string> newDownloadGrouping = new List <string> {
                                    thisFileInfo.Name
                                };
                                download_files[filename_sans_extension.ToLower()] = newDownloadGrouping;
                            }
                        }
                    }
                }
            }

            // This package is good to go, so build it, save, etc...
            try
            {
                // Save the METS file to the database and back to the directory
                Item_To_Complete.Source_Directory = digitalResourceDirectory;

                // Step through and add each file
                Item_To_Complete.Divisions.Download_Tree.Clear();

                // Step through each file
                bool error_reading_file_occurred = false;

                // Add the image files first
                bool jpeg_added = false;
                bool jp2_added  = false;
                foreach (string thisFileKey in image_files.Keys)
                {
                    // Get the list of files
                    List <string> theseFiles = image_files[thisFileKey];

                    // Add each file
                    foreach (string thisFile in theseFiles)
                    {
                        // Create the new file object and compute a label
                        System.IO.FileInfo fileInfo = new System.IO.FileInfo(thisFile);
                        SobekCM.Resource_Object.Divisions.SobekCM_File_Info newFile = new SobekCM.Resource_Object.Divisions.SobekCM_File_Info(fileInfo.Name);
                        string label = fileInfo.Name.Replace(fileInfo.Extension, "");
                        if (System.Web.HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey] != null)
                        {
                            string possible_label = System.Web.HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey].ToString();
                            if (possible_label.Length > 0)
                            {
                                label = possible_label;
                            }
                        }

                        // Add this file
                        item.Divisions.Physical_Tree.Add_File(newFile, label);

                        // Seperate code for JP2 and JPEG type files
                        string extension = fileInfo.Extension.ToUpper();
                        if (extension.IndexOf("JP2") >= 0)
                        {
                            if (!error_reading_file_occurred)
                            {
                                if (!newFile.Compute_Jpeg2000_Attributes(item.Source_Directory))
                                {
                                    error_reading_file_occurred = true;
                                }
                            }
                            jp2_added = true;
                        }
                        else
                        {
                            if (!error_reading_file_occurred)
                            {
                                if (!newFile.Compute_Jpeg_Attributes(item.Source_Directory))
                                {
                                    error_reading_file_occurred = true;
                                }
                            }
                            jpeg_added = true;
                        }
                    }
                }

                // Add the download files next
                foreach (string thisFileKey in download_files.Keys)
                {
                    // Get the list of files
                    List <string> theseFiles = download_files[thisFileKey];

                    // Add each file
                    foreach (string thisFile in theseFiles)
                    {
                        // Create the new file object and compute a label
                        FileInfo          fileInfo = new FileInfo(thisFile);
                        SobekCM_File_Info newFile  = new SobekCM_File_Info(fileInfo.Name);
                        string            label    = fileInfo.Name.Replace(fileInfo.Extension, "");
                        if (HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey] != null)
                        {
                            string possible_label = HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey].ToString();
                            if (possible_label.Length > 0)
                            {
                                label = possible_label;
                            }
                        }

                        // Add this file
                        Item_To_Complete.Divisions.Download_Tree.Add_File(newFile, label);
                    }
                }

                // Add the JPEG2000 and JPEG-specific viewers
                item.Behaviors.Clear_Views();
                if (jpeg_added)
                {
                    item.Behaviors.Add_View(SobekCM.Resource_Object.Behaviors.View_Enum.JPEG);
                }
                if (jp2_added)
                {
                    item.Behaviors.Add_View(SobekCM.Resource_Object.Behaviors.View_Enum.JPEG2000);
                }


                // Determine the total size of the package before saving
                string[] all_files_final = Directory.GetFiles(digitalResourceDirectory);
                double   size            = all_files_final.Aggregate <string, double>(0, (current, thisFile) => current + (((new FileInfo(thisFile)).Length) / 1024));
                Item_To_Complete.DiskSize_MB = size;

                // Save to the database
                try
                {
                    SobekCM_Database.Save_Digital_Resource(Item_To_Complete);
                    SobekCM_Database.Save_Behaviors(Item_To_Complete, Item_To_Complete.Behaviors.Text_Searchable, false);
                }
                catch (Exception ee)
                {
                    StreamWriter writer = new StreamWriter(digitalResourceDirectory + "\\exception.txt", false);
                    writer.WriteLine("ERROR CAUGHT WHILE SAVING DIGITAL RESOURCE");
                    writer.WriteLine(DateTime.Now.ToString());
                    writer.WriteLine();
                    writer.WriteLine(ee.Message);
                    writer.WriteLine(ee.StackTrace);
                    writer.Flush();
                    writer.Close();
                    throw;
                }


                // Assign the file root and assoc file path
                Item_To_Complete.Web.File_Root     = Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8, 2);
                Item_To_Complete.Web.AssocFilePath = Item_To_Complete.Web.File_Root + "\\" + Item_To_Complete.VID + "\\";

                // Create the static html pages
                string base_url = currentMode.Base_URL;
                try
                {
                    Static_Pages_Builder staticBuilder = new Static_Pages_Builder(SobekCM_Library_Settings.System_Base_URL, SobekCM_Library_Settings.Base_Data_Directory, Translator, codeManager, itemList, iconList, webSkin);
                    string filename = digitalResourceDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html";
                    staticBuilder.Create_Item_Citation_HTML(Item_To_Complete, filename, String.Empty);
                }
                catch (Exception ee)
                {
                    string error = ee.Message;
                }

                currentMode.Base_URL = base_url;

                // Save the rest of the metadata
                Item_To_Complete.Save_SobekCM_METS();

                // Finally, set the item for more processing if there were any files
                if (((image_files.Count > 0) || (download_files.Count > 0)) && (Item_To_Complete.Web.ItemID > 0))
                {
                    Database.SobekCM_Database.Update_Additional_Work_Needed_Flag(Item_To_Complete.Web.ItemID, true, Tracer);
                }
            }
            catch (Exception ee)
            {
                validationErrors.Add("Error encountered during item save!");
                validationErrors.Add(ee.ToString().Replace("\r", "<br />"));

                // Set an initial flag
                criticalErrorEncountered = true;

                string error_body    = "<strong>ERROR ENCOUNTERED DURING ONLINE FILE MANAGEMENT</strong><br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + base.currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + base.currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a><br />User: "******"<br /><br /></blockquote>" + ee.ToString().Replace("\n", "<br />");
                string error_subject = "Error during file management for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                string email_to      = SobekCM_Library_Settings.System_Error_Email;
                if (email_to.Length == 0)
                {
                    email_to = SobekCM_Library_Settings.System_Email;
                }
                Database.SobekCM_Database.Send_Database_Email(email_to, error_subject, error_body, true, false, -1);
            }


            return(criticalErrorEncountered);
        }
        private bool complete_item_submission(SobekCM_Item Item_To_Complete,  Custom_Tracer Tracer )
        {
            // Set an initial flag
            criticalErrorEncountered = false;

            string[] all_files = Directory.GetFiles(userInProcessDirectory);
            SortedList<string, List<string>> image_files = new SortedList<string, List<string>>();
            SortedList<string, List<string>> download_files = new SortedList<string, List<string>>();
            foreach (string thisFile in all_files)
            {
                FileInfo thisFileInfo = new FileInfo(thisFile);

                if ((thisFileInfo.Name.IndexOf("agreement.txt") != 0) && (thisFileInfo.Name.IndexOf("TEMP000001_00001.mets") != 0) && (thisFileInfo.Name.IndexOf("doc.xml") != 0) && (thisFileInfo.Name.IndexOf("ufdc_mets.xml") != 0) && (thisFileInfo.Name.IndexOf("marc.xml") != 0))
                {
                    // Get information about this files name and extension
                    string extension_upper = thisFileInfo.Extension.ToUpper();
                    string filename_sans_extension = thisFileInfo.Name.Replace(thisFileInfo.Extension, "");
                    string name_upper = thisFileInfo.Name.ToUpper();

                    // Is this a page image?
                    if ((extension_upper == ".JPG") || (extension_upper == ".TIF") || (extension_upper == ".JP2") || (extension_upper == ".JPX"))
                    {
                        // Exclude .QC.jpg files
                        if (name_upper.IndexOf(".QC.JPG") < 0)
                        {
                            // If this is a thumbnail, trim off the THM part on the file name
                            if (name_upper.IndexOf("THM.JPG") > 0)
                            {
                                filename_sans_extension = filename_sans_extension.Substring(0, filename_sans_extension.Length - 3);
                            }

                            // Is this the first image file with this name?
                            if (image_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                image_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List<string> newImageGrouping = new List<string> {thisFileInfo.Name};
                                image_files[filename_sans_extension.ToLower()] = newImageGrouping;
                            }
                        }
                    }
                    else
                    {
                        // If this does not match the exclusion regular expression, than add this
                        if (!Regex.Match(thisFileInfo.Name, SobekCM_Library_Settings.Files_To_Exclude_From_Downloads, RegexOptions.IgnoreCase).Success)
                        {
                            // Is this the first image file with this name?
                            if (download_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                download_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List<string> newDownloadGrouping = new List<string> {thisFileInfo.Name};
                                download_files[filename_sans_extension.ToLower()] = newDownloadGrouping;
                            }
                        }
                    }
                }
            }

            // This package is good to go, so build it, save, etc...
            try
            {
                // Save the METS file to the database and back to the directory
                Item_To_Complete.Source_Directory = userInProcessDirectory;

                // Step through and add each file
                Item_To_Complete.Divisions.Download_Tree.Clear();
                if ((template.Upload_Types == Template.Template_Upload_Types.File_or_URL) || (template.Upload_Types == Template.Template_Upload_Types.File))
                {
                    // Step through each file

                    bool error_reading_file_occurred = false;

                    // Add the image files first
                    bool jpeg_added = false;
                    bool jp2_added = false;
                    foreach(string thisFileKey in image_files.Keys )
                    {
                        // Get the list of files
                        List<string> theseFiles = image_files[thisFileKey];

                        // Add each file
                        foreach (string thisFile in theseFiles)
                        {
                            // Create the new file object and compute a label
                            FileInfo fileInfo = new FileInfo(thisFile);
                            SobekCM_File_Info newFile = new SobekCM_File_Info(fileInfo.Name);
                            string label = fileInfo.Name.Replace(fileInfo.Extension, "");
                            if (HttpContext.Current.Session["file_" + thisFileKey] != null)
                            {
                                string possible_label = HttpContext.Current.Session["file_" + thisFileKey].ToString();
                                if (possible_label.Length > 0)
                                    label = possible_label;
                            }

                            // Add this file
                            Item_To_Complete.Divisions.Physical_Tree.Add_File(newFile, label);

                            // Seperate code for JP2 and JPEG type files
                            string extension = fileInfo.Extension.ToUpper();
                            if (extension.IndexOf("JP2") >= 0)
                            {
                                if (!error_reading_file_occurred)
                                {
                                    if (!newFile.Compute_Jpeg2000_Attributes(userInProcessDirectory))
                                        error_reading_file_occurred = true;
                                }
                                jp2_added = true;
                            }
                            else
                            {
                                if (!error_reading_file_occurred)
                                {
                                    if (!newFile.Compute_Jpeg_Attributes(userInProcessDirectory))
                                        error_reading_file_occurred = true;
                                }
                                jpeg_added = true;
                            }
                        }
                    }

                    // Add the download files next
                    foreach(string thisFileKey in download_files.Keys )
                    {
                        // Get the list of files
                        List<string> theseFiles = download_files[thisFileKey];

                        // Add each file
                        foreach (string thisFile in theseFiles)
                        {
                            // Create the new file object and compute a label
                            FileInfo fileInfo = new FileInfo(thisFile);
                            SobekCM_File_Info newFile = new SobekCM_File_Info(fileInfo.Name);
                            string label = fileInfo.Name.Replace( fileInfo.Extension, "");
                            if (HttpContext.Current.Session["file_" + thisFileKey] != null)
                            {
                                string possible_label = HttpContext.Current.Session["file_" + thisFileKey].ToString();
                                if (possible_label.Length > 0)
                                    label = possible_label;
                            }

                            // Add this file
                            Item_To_Complete.Divisions.Download_Tree.Add_File(newFile, label);
                        }
                    }

                    // Add the JPEG2000 and JPEG-specific viewers
                    Item_To_Complete.Behaviors.Clear_Views();
                    if (jpeg_added)
                    {
                        Item_To_Complete.Behaviors.Add_View(View_Enum.JPEG);
                    }
                    if (jp2_added)
                    {
                        Item_To_Complete.Behaviors.Add_View(View_Enum.JPEG2000);
                    }
                }

                // Determine the total size of the package before saving
                string[] all_files_final = Directory.GetFiles(userInProcessDirectory);
                double size = all_files_final.Aggregate<string, double>(0, (current, thisFile) => current + (((new FileInfo(thisFile)).Length)/1024));
                Item_To_Complete.DiskSize_MB = size;

                // BibID and VID will be automatically assigned
                Item_To_Complete.BibID = template.BibID_Root;
                Item_To_Complete.VID = String.Empty;

                // Set some values in the tracking portion
                if (Item_To_Complete.Divisions.Files.Count > 0)
                {
                    Item_To_Complete.Tracking.Born_Digital = true;
                }
                Item_To_Complete.Tracking.VID_Source = "SobekCM:" + templateCode;

                // Save to the database
                try
                {
                    SobekCM_Database.Save_New_Digital_Resource(Item_To_Complete, false, true, user.UserName, String.Empty, user.UserID);
                }
                catch (Exception ee)
                {
                    StreamWriter writer = new StreamWriter(userInProcessDirectory + "\\exception.txt", false);
                    writer.WriteLine( "ERROR CAUGHT WHILE SAVING NEW DIGITAL RESOURCE");
                    writer.WriteLine( DateTime.Now.ToString());
                    writer.WriteLine();
                    writer.WriteLine( ee.Message );
                    writer.WriteLine( ee.StackTrace );
                    writer.Flush();
                    writer.Close();
                    throw;
                }

                // Assign the file root and assoc file path
                Item_To_Complete.Web.File_Root = Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8, 2);
                Item_To_Complete.Web.AssocFilePath = Item_To_Complete.Web.File_Root + "\\" + Item_To_Complete.VID + "\\";

                // Create the static html pages
                string base_url = currentMode.Base_URL;
                try
                {
                    Static_Pages_Builder staticBuilder = new Static_Pages_Builder(SobekCM_Library_Settings.System_Base_URL, SobekCM_Library_Settings.Base_Data_Directory, Translator, codeManager, itemList, iconList, webSkin);
                    string filename = userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html";
                    staticBuilder.Create_Item_Citation_HTML(Item_To_Complete, filename, String.Empty);
                }
                catch (Exception)
                {
                    // An error here is not catastrophic
                }

                currentMode.Base_URL = base_url;

                // Save the rest of the metadata
                Item_To_Complete.Save_SobekCM_METS();
                Item_To_Complete.Save_Citation_Only_METS();

                // Add this to the cache
                itemList.Add_SobekCM_Item(Item_To_Complete);

                //// Link this item and user
                //Database.SobekCM_Database.Add_User_Item_Link(user.UserID, item.Web.ItemID, 1, true);
                //Database.SobekCM_Database.Add_User_BibID_Link(user.UserID, item.Behaviors.GroupID);
                //Database.SobekCM_Database.Add_Item_To_User_Folder(user.UserID, "Submitted Items", item.BibID, item.VID, 0, String.Empty, Tracer);

                // Save Bib_Level METS?
                //SobekCM.Resource_Object.Writers.OAI_Writer oaiWriter = new SobekCM.Resource_Object.Writers.OAI_Writer();
                //oaiWriter.Save_OAI_File(bibPackage, resource_folder + "\\oai_dc.xml", bibPackage.Processing_Parameters.Collection_Primary.ToLower(), createDate);

                List<string> collectionnames = new List<string>();
                //// Get the collection names
                //if (item.Processing_Parameters.Collection_Primary.Length > 0)
                //{
                //    DataRow[] primCode = Collection_Codes.Select("collectioncode = '" + item.Processing_Parameters.Collection_Primary + "'");
                //    if (primCode.Length > 0)
                //    {
                //        collectionnames.Add(primCode[0]["ShortName"].ToString());
                //    }
                //}
                //foreach (string altCollection in bibPackage.Processing_Parameters.Collections_Alternate)
                //{
                //    DataRow[] altCode = Collection_Codes.Select("collectioncode = '" + altCollection + "'");
                //    if (altCode.Length > 0)
                //    {
                //        collectionnames.Add(altCode[0]["ShortName"].ToString());
                //    }
                //}
                // Save the marc xml file
                MarcXML_File_ReaderWriter marcWriter = new MarcXML_File_ReaderWriter();
                string Error_Message;
                Dictionary<string, object> options = new Dictionary<string, object>();
                options["MarcXML_File_ReaderWriter:Additional_Tags"] = Item_To_Complete.MARC_Sobek_Standard_Tags(collectionnames, true, SobekCM_Library_Settings.System_Name, SobekCM_Library_Settings.System_Abbreviation);
                marcWriter.Write_Metadata(Item_To_Complete.Source_Directory + "\\marc.xml", Item_To_Complete, options, out Error_Message);

                // Delete the TEMP mets file
                if (File.Exists(userInProcessDirectory + "\\TEMP000001_00001.mets"))
                    File.Delete(userInProcessDirectory + "\\TEMP000001_00001.mets");

                // Rename the METS file to the XML file
                if ((!File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets.xml")) &&
                    (File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets")))
                {
                    File.Move(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets", userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".mets.xml");
                }

                // Copy this to all the image servers
                SobekCM_Library_Settings.Refresh(Database.SobekCM_Database.Get_Settings_Complete(Tracer));
                string[] allFiles = Directory.GetFiles(userInProcessDirectory);

                string serverNetworkFolder = SobekCM_Library_Settings.Image_Server_Network + Item_To_Complete.Web.AssocFilePath;

                // Create the folder
                if (!Directory.Exists(serverNetworkFolder))
                    Directory.CreateDirectory(serverNetworkFolder);

                foreach (string thisFile in allFiles)
                {
                    string destination_file = serverNetworkFolder + "\\" + (new FileInfo(thisFile)).Name;
                    File.Copy(thisFile, destination_file, true);
                }

                // Copy the static HTML file as well
                try
                {
                    if (!Directory.Exists(SobekCM_Library_Settings.Static_Pages_Location + Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8)))
                        Directory.CreateDirectory(SobekCM_Library_Settings.Static_Pages_Location + Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8));
                    if (File.Exists(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html"))
                        File.Copy(userInProcessDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html", SobekCM_Library_Settings.Static_Pages_Location + Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8) + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html", true);
                }
                catch (Exception)
                {
                    // An error here is not catastrophic
                }

                // Add this to the cache
                itemList.Add_SobekCM_Item(Item_To_Complete);

                // Incrememnt the count of number of items submitted by this user
                user.Items_Submitted_Count++;
                if (!user.BibIDs.Contains(Item_To_Complete.BibID))
                    user.Add_BibID(Item_To_Complete.BibID);

                // Now, delete all the files here
                all_files = Directory.GetFiles(userInProcessDirectory);
                foreach (string thisFile in all_files)
                {
                    File.Delete(thisFile);
                }

                // Finally, set the item for more processing if there were any files
                if (((image_files.Count > 0) || (download_files.Count > 0)) && ( Item_To_Complete.Web.ItemID > 0 ))
                {
                    Database.SobekCM_Database.Update_Additional_Work_Needed_Flag(Item_To_Complete.Web.ItemID, true, Tracer);
                }

                // Clear any temporarily assigned current project and template
                user.Current_Project = null;
                user.Current_Template = null;

            }
            catch (Exception ee)
            {
                validationErrors.Add("Error encountered during item save!");
                validationErrors.Add(ee.ToString().Replace("\r", "<br />"));

                // Set an initial flag
                criticalErrorEncountered = true;

                string error_body = "<strong>ERROR ENCOUNTERED DURING ONLINE SUBMITTAL PROCESS</strong><br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a><br />User: "******"<br /><br /></blockquote>" + ee.ToString().Replace("\n", "<br />");
                string error_subject = "Error during submission for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                string email_to = SobekCM_Library_Settings.System_Error_Email;
                if (email_to.Length == 0)
                    email_to = SobekCM_Library_Settings.System_Email;
                Database.SobekCM_Database.Send_Database_Email(email_to, error_subject, error_body, true, false, -1);
            }

            if (!criticalErrorEncountered)
            {
                // Send email to the email from the template, if one was provided

                if (template.Email_Upon_Receipt.Length > 0)
                {
                    string body = "New item submission complete!<br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Submittor: " + user.Full_Name + " ( " + user.Email + " )<br />Link: <a href=\"" + currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + Item_To_Complete.BibID + ":" + Item_To_Complete.VID + "</a></blockquote>";
                    string subject = "Item submission complete for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                    Database.SobekCM_Database.Send_Database_Email(template.Email_Upon_Receipt, subject, body, true, false, -1);
                }

                // If the user wants to have a message sent, send one
                if (user.Send_Email_On_Submission)
                {
                    // Create the mail message
                    string body2 = "<strong>CONGRATULATIONS!</strong><br /><br />Your item has been successfully added to the digital library and will appear immediately.  Search indexes may take a couple minutes to build, at which time this item will be discoverable through the search interface. <br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a></blockquote>";
                    string subject2 = "Item submission complete for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                    Database.SobekCM_Database.Send_Database_Email(user.Email, subject2, body2, true, false, -1 );
                }
            }

            return criticalErrorEncountered;
        }
Exemplo n.º 15
0
 /// <summary> Adds a file  object (with the appropriate divisions and pages) to this tree </summary>
 /// <param name="New_File"> New file object to add </param>
 /// <remarks> This is generally used to add just a single file.  To add many files, better logic should be implemented </remarks>
 public void Add_File(SobekCM_File_Info New_File)
 {
     Add_File(New_File, String.Empty);
 }
        /// <summary> Adds all of the file information to a digital resource package by analyzing the directory </summary>
        /// <param name="BIBPackage">Digital resource package to enrich</param>
        /// <param name="FilesFilter"> Files to be added as page image files ( such as "*.tif|*.jpg|*.jp2" )</param>
        /// <param name="RecursivelyIncludeSubfolders"> Flag indicates if all files in subfolders should also be added </param>
        /// <param name="PageImagesInSeperateFoldersCanBeSamePage"> If two images with the same root are found in subfolders, should </param>
        public static void Add_All_Files(SobekCM_Item BIBPackage, string FilesFilter, bool RecursivelyIncludeSubfolders, bool PageImagesInSeperateFoldersCanBeSamePage)
        {
            // Get the set of file filters within a list
            List<string> file_filters = new List<string>();
            if (FilesFilter.IndexOf("|") < 0)
            {
                file_filters.Add(FilesFilter.ToUpper());
            }
            else
            {
                string[] splitter = FilesFilter.Split("|".ToCharArray());
                foreach (string thisFilter in splitter)
                {
                    file_filters.Add(thisFilter.ToUpper());
                }
            }

            // Get the files from the current directory (or recursive directories)
            Builder_Page_File_Collection fileCollection = new Builder_Page_File_Collection();
            get_files_from_current_directory(fileCollection, file_filters, BIBPackage.Source_Directory, String.Empty, RecursivelyIncludeSubfolders);

            // Now, determine which files are already in the METS file.
            // Build a collection of file objects from the METS
            List<SobekCM_File_Info> metsFiles = new List<SobekCM_File_Info>();
            Builder_Page_File_Collection metsFileCollection = new Builder_Page_File_Collection();
            Dictionary<SobekCM_File_Info, Page_TreeNode> fileToPage = new Dictionary<SobekCM_File_Info, Page_TreeNode>();
            Dictionary<Page_TreeNode, Division_TreeNode> pageToDiv = new Dictionary<Page_TreeNode, Division_TreeNode>();

            foreach (abstract_TreeNode rootNode in BIBPackage.Divisions.Physical_Tree.Roots)
            {
                recursively_add_all_METS_files(rootNode, metsFiles, metsFileCollection, fileToPage, pageToDiv, file_filters);
            }

            // Determine which files to delete from the METS package
            List<SobekCM_File_Info> deletes = new List<SobekCM_File_Info>();
            foreach (SobekCM_File_Info thisFile in metsFiles)
            {
                if ((thisFile.METS_LocType == SobekCM_File_Info_Type_Enum.SYSTEM) && (!File.Exists(BIBPackage.Source_Directory + "//" + thisFile.System_Name)))
                {
                    deletes.Add(thisFile);
                }
            }

            // Delete the files, and related pages
            foreach (SobekCM_File_Info thisFile in deletes)
            {
                metsFiles.Remove(thisFile);

                Page_TreeNode thisPage = fileToPage[thisFile];
                if (thisPage != null)
                {
                    thisPage.Files.Remove(thisFile);
                    Division_TreeNode thisDiv = pageToDiv[thisPage];
                    if (thisDiv != null)
                    {
                        thisDiv.Nodes.Remove(thisPage);
                    }
                }

                // Remove this from the other mets list
                int index = 0;
                int deleteIndex = -1;
                foreach (Builder_Page_File thisPageFile in metsFileCollection)
                {
                    if (thisPageFile.FullName.ToUpper() == thisFile.System_Name.ToUpper())
                    {
                        deleteIndex = index;
                        break;
                    }

                    index++;
                }
                if (deleteIndex >= 0)
                {
                    metsFileCollection.RemoveAt(deleteIndex);
                }
            }

            // Now, recursively check each division and remove empty divisions
            int rootNodeCounter = 0;
            while (rootNodeCounter < BIBPackage.Divisions.Physical_Tree.Roots.Count)
            {
                abstract_TreeNode rootNode = BIBPackage.Divisions.Physical_Tree.Roots[rootNodeCounter];
                if (recursively_remove_empty_divisions(rootNode))
                    BIBPackage.Divisions.Physical_Tree.Roots.Remove(rootNode);
                else
                    rootNodeCounter++;
            }

            // Build the list of all the remaining files
            Hashtable filesPresent = new Hashtable();
            foreach (SobekCM_File_Info thisFile in metsFiles)
            {
                filesPresent[thisFile.System_Name] = thisFile;
            }

            // Determine which files need to be added
            Builder_Page_File_Collection addFiles = new Builder_Page_File_Collection();
            foreach (Builder_Page_File thisFile in fileCollection)
            {
                if (!filesPresent.Contains(thisFile.FullName_With_Relative_Directory))
                {
                    addFiles.Add(thisFile);
                }
            }

            // Add files that need to be added
            if (addFiles.Count > 0)
            {
                // Make sure there is at least one division
                if (BIBPackage.Divisions.Physical_Tree.Roots.Count == 0)
                {
                    Division_TreeNode newRootNode = new Division_TreeNode("Main", String.Empty);
                    BIBPackage.Divisions.Physical_Tree.Roots.Add(newRootNode);
                }

                // Create the map of file names to pages
                Dictionary<string, Page_TreeNode> file_to_page_hash = new Dictionary<string, Page_TreeNode>();
                List<abstract_TreeNode> pageNodes = BIBPackage.Divisions.Physical_Tree.Pages_PreOrder;
                foreach (Page_TreeNode pageNode in pageNodes)
                {
                    if (pageNode.Files.Count > 0)
                    {
                        string first_page_name = pageNode.Files[0].File_Name_Sans_Extension;

                        if (first_page_name.IndexOf(".") > 0)
                            first_page_name = first_page_name.Substring(0, first_page_name.IndexOf("."));

                        if ((PageImagesInSeperateFoldersCanBeSamePage) || (pageNode.Files[0].METS_LocType == SobekCM_File_Info_Type_Enum.URL))
                        {
                            if (first_page_name.IndexOf("\\") > 0)
                            {
                                string[] slash_splitter = first_page_name.Split("\\".ToCharArray());
                                first_page_name = slash_splitter[slash_splitter.Length - 1];
                            }
                        }

                        if (!file_to_page_hash.ContainsKey(first_page_name.ToUpper()))
                        {
                            file_to_page_hash[first_page_name.ToUpper()] = pageNode;
                        }
                    }
                }

                // If there are no existing pages, this can be easily assembled
                if (metsFiles.Count == 0)
                {
                    try
                    {
                        // Get the first division
                        Division_TreeNode firstDiv = (Division_TreeNode) BIBPackage.Divisions.Physical_Tree.Roots[0];

                        // Add each file
                        foreach (Builder_Page_File thisFile in addFiles)
                        {
                            // Create the new METS file object
                            SobekCM_File_Info newFileForMETS = new SobekCM_File_Info(thisFile.FullName_With_Relative_Directory);

                            // Get the root of this file, to put all files of the same root on the same page
                            string thisFileShort = newFileForMETS.File_Name_Sans_Extension;
                            if (PageImagesInSeperateFoldersCanBeSamePage)
                            {
                                if (thisFileShort.IndexOf("\\") > 0)
                                {
                                    string[] slash_splitter = thisFileShort.Split("\\".ToCharArray());
                                    thisFileShort = slash_splitter[slash_splitter.Length - 1];
                                }
                            }

                            // Is this a pre-existing root ( therefore pre-existing page )?
                            if (file_to_page_hash.ContainsKey(thisFileShort))
                            {
                                // Just add this file to the pre-existing page
                                file_to_page_hash[thisFileShort].Files.Add(newFileForMETS);
                            }
                            else
                            {
                                // This needs a new page then
                                Page_TreeNode newPage = new Page_TreeNode();
                                newPage.Files.Add(newFileForMETS);
                                firstDiv.Nodes.Add(newPage);

                                // Add this page to the hash, so it is not added again later
                                file_to_page_hash[thisFileShort] = newPage;
                            }
                        }
                    }
                    catch
                    {
                    }
                }
                else
                {
                    // Configure the initial pointers
                    Builder_Page_File previous_file = null;
                    Builder_Page_File next_file = metsFileCollection[0];
                    Builder_Page_File new_file = addFiles[0];
                    int new_file_counter = 1;
                    int next_file_counter = 1;

                    // Loop through each file to be added
                    while (new_file != null)
                    {
                        // Create the new METS file object
                        SobekCM_File_Info newFileForMETS = new SobekCM_File_Info(new_file.FullName_With_Relative_Directory);

                        // Get the root of this file, to put all files of the same root on the same page
                        string thisFileShort = newFileForMETS.File_Name_Sans_Extension;
                        if (PageImagesInSeperateFoldersCanBeSamePage)
                        {
                            if (thisFileShort.IndexOf("\\") > 0)
                            {
                                string[] slash_splitter = thisFileShort.Split("\\".ToCharArray());
                                thisFileShort = slash_splitter[slash_splitter.Length - 1];
                            }
                        }

                        // First, ensure that we have not already added a page for this
                        if (file_to_page_hash.ContainsKey(thisFileShort))
                        {
                            // Just add this file to the pre-existing page
                            file_to_page_hash[thisFileShort].Files.Add(newFileForMETS);
                        }
                        else
                        {
                            // Move to the right part of the existing files list
                            while ((new_file.CompareTo(next_file) > 0) && (next_file != null))
                            {
                                previous_file = next_file;
                                if (next_file_counter < metsFileCollection.Count)
                                {
                                    next_file = metsFileCollection[next_file_counter++];
                                }
                                else
                                {
                                    next_file = null;
                                }
                            }

                            // Add the page for this and link the new file
                            Page_TreeNode newPage = new Page_TreeNode();
                            newPage.Files.Add(newFileForMETS);
                            file_to_page_hash[thisFileShort] = newPage;

                            // Get the parent division and add this page in the right place
                            // Check there was a previous page, otherwise this inserts at the very beginning
                            if (previous_file == null)
                            {
                                abstract_TreeNode abstractNode = BIBPackage.Divisions.Physical_Tree.Roots[0];
                                Division_TreeNode lastDivNode = (Division_TreeNode) abstractNode;
                                while (!abstractNode.Page)
                                {
                                    lastDivNode = (Division_TreeNode) abstractNode;
                                    if (lastDivNode.Nodes.Count > 0)
                                    {
                                        abstractNode = lastDivNode.Nodes[0];
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                lastDivNode.Nodes.Insert(0, newPage);
                                metsFileCollection.Insert(new_file);
                                new_file.METS_Division = lastDivNode;
                                new_file.METS_Page = newPage;
                                next_file = metsFileCollection[0];
                            }
                            else
                            {
                                Division_TreeNode parentDivNode = previous_file.METS_Division;
                                Page_TreeNode previousPageNode = previous_file.METS_Page;
                                int previousFileIndex = parentDivNode.Nodes.IndexOf(previousPageNode);
                                if (previousFileIndex + 1 >= parentDivNode.Nodes.Count)
                                    parentDivNode.Nodes.Add(newPage);
                                else
                                    parentDivNode.Nodes.Insert(previousFileIndex + 1, newPage);
                                next_file = previous_file;
                                next_file_counter--;
                                new_file.METS_Division = parentDivNode;
                                new_file.METS_Page = newPage;
                                metsFileCollection.Insert(new_file);
                            }
                        }

                        // Move to the next new file
                        if (new_file_counter < addFiles.Count)
                        {
                            new_file = addFiles[new_file_counter++];
                        }
                        else
                        {
                            new_file = null;
                        }
                    }
                }
            }
        }
        private bool complete_item_submission(SobekCM_Item Item_To_Complete, Custom_Tracer Tracer )
        {
            // Set an initial flag
            criticalErrorEncountered = false;

            string[] all_files = Directory.GetFiles(digitalResourceDirectory);
            SortedList<string, List<string>> image_files = new SortedList<string, List<string>>();
            SortedList<string, List<string>> download_files = new SortedList<string, List<string>>();
            foreach (string thisFile in all_files)
            {
                FileInfo thisFileInfo = new FileInfo(thisFile);

                if ((thisFileInfo.Name.IndexOf("agreement.txt") != 0) && (thisFileInfo.Name.IndexOf("TEMP000001_00001.mets") != 0) && (thisFileInfo.Name.IndexOf("doc.xml") != 0) && (thisFileInfo.Name.IndexOf("marc.xml") != 0))
                {
                    // Get information about this files name and extension
                    string extension_upper = thisFileInfo.Extension.ToUpper();
                    string filename_sans_extension = thisFileInfo.Name.Replace(thisFileInfo.Extension, "");
                    string name_upper = thisFileInfo.Name.ToUpper();

                    // Is this a page image?
                    if ((extension_upper == ".JPG") || (extension_upper == ".TIF") || (extension_upper == ".JP2") || (extension_upper == ".JPX"))
                    {
                        // Exclude .QC.jpg files
                        if (name_upper.IndexOf(".QC.JPG") < 0)
                        {
                            // If this is a thumbnail, trim off the THM part on the file name
                            if (name_upper.IndexOf("THM.JPG") > 0)
                            {
                                filename_sans_extension = filename_sans_extension.Substring(0, filename_sans_extension.Length - 3);
                            }

                            // Is this the first image file with this name?
                            if (image_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                image_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List<string> newImageGrouping = new List<string> {thisFileInfo.Name};
                                image_files[filename_sans_extension.ToLower()] = newImageGrouping;
                            }
                        }
                    }
                    else
                    {
                        // If this does not match the exclusion regular expression, than add this
                        if ((!Regex.Match(thisFileInfo.Name, UI_ApplicationCache_Gateway.Settings.Resources.Files_To_Exclude_From_Downloads, RegexOptions.IgnoreCase).Success) && ( String.Compare(thisFileInfo.Name, Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html", StringComparison.OrdinalIgnoreCase) != 0 ))
                        {
                            // Also, exclude files that are .XML and marc.xml, or doc.xml, or have the bibid in the name
                            if ((thisFileInfo.Name.IndexOf("marc.xml", StringComparison.OrdinalIgnoreCase) != 0) && (thisFileInfo.Name.IndexOf("marc.xml", StringComparison.OrdinalIgnoreCase) != 0) && (thisFileInfo.Name.IndexOf(".mets", StringComparison.OrdinalIgnoreCase) < 0) && (thisFileInfo.Name.IndexOf("citation_mets.xml", StringComparison.OrdinalIgnoreCase) < 0) &&
                                ((thisFileInfo.Name.IndexOf(".xml", StringComparison.OrdinalIgnoreCase) < 0) || (thisFileInfo.Name.IndexOf( Item_To_Complete.BibID, StringComparison.OrdinalIgnoreCase) < 0)))
                            {
                                // Is this the first image file with this name?
                                if (download_files.ContainsKey(filename_sans_extension.ToLower()))
                                {
                                    download_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                                }
                                else
                                {
                                    List<string> newDownloadGrouping = new List<string> {thisFileInfo.Name};
                                    download_files[filename_sans_extension.ToLower()] = newDownloadGrouping;
                                }
                            }
                        }
                    }
                }
            }

            // This package is good to go, so build it, save, etc...
            try
            {
                // Save the METS file to the database and back to the directory
                Item_To_Complete.Source_Directory = digitalResourceDirectory;

                // Step through and add each file
                Item_To_Complete.Divisions.Download_Tree.Clear();

                // Add the download files next
                foreach (string thisFileKey in download_files.Keys)
                {
                    // Get the list of files
                    List<string> theseFiles = download_files[thisFileKey];

                    // Add each file
                    foreach (string thisFile in theseFiles)
                    {
                        // Create the new file object and compute a label
                        FileInfo fileInfo = new FileInfo(thisFile);
                        SobekCM_File_Info newFile = new SobekCM_File_Info(fileInfo.Name);
                        string label = fileInfo.Name.Replace(fileInfo.Extension, "");
                        if (HttpContext.Current.Session["file_" + RequestSpecificValues.Current_Item.Web.ItemID + "_" + thisFileKey] != null)
                        {
                            string possible_label = HttpContext.Current.Session["file_" + RequestSpecificValues.Current_Item.Web.ItemID + "_" + thisFileKey].ToString();
                            if (possible_label.Length > 0)
                                label = possible_label;
                        }

                        // Add this file
                        Item_To_Complete.Divisions.Download_Tree.Add_File(newFile, label);
                    }
                }

                // Determine the total size of the package before saving
                string[] all_files_final = Directory.GetFiles(digitalResourceDirectory);
                double size = all_files_final.Aggregate<string, double>(0, (Current, ThisFile) => Current + (((new FileInfo(ThisFile)).Length)/1024));
                Item_To_Complete.DiskSize_KB = size;

                // Create the options dictionary used when saving information to the database, or writing MarcXML
                Dictionary<string, object> options = new Dictionary<string, object>();
                if (UI_ApplicationCache_Gateway.Settings.MarcGeneration != null)
                {
                    options["MarcXML_File_ReaderWriter:MARC Cataloging Source Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Cataloging_Source_Code;
                    options["MarcXML_File_ReaderWriter:MARC Location Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Location_Code;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Agency"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Agency;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Place"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Place;
                    options["MarcXML_File_ReaderWriter:MARC XSLT File"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.XSLT_File;
                }
                options["MarcXML_File_ReaderWriter:System Name"] = UI_ApplicationCache_Gateway.Settings.System.System_Name;
                options["MarcXML_File_ReaderWriter:System Abbreviation"] = UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation;

                // Save to the database
                try
                {
                    SobekCM_Database.Save_Digital_Resource( Item_To_Complete, options  );
                    SobekCM_Database.Save_Behaviors(Item_To_Complete, Item_To_Complete.Behaviors.Text_Searchable, false, false);
                }
                catch (Exception ee)
                {
                    StreamWriter writer = new StreamWriter(digitalResourceDirectory + "\\exception.txt", false);
                    writer.WriteLine( "ERROR CAUGHT WHILE SAVING DIGITAL RESOURCE");
                    writer.WriteLine( DateTime.Now.ToString());
                    writer.WriteLine();
                    writer.WriteLine( ee.Message );
                    writer.WriteLine( ee.StackTrace );
                    writer.Flush();
                    writer.Close();
                    throw;
                }

                // Assign the file root and assoc file path
                Item_To_Complete.Web.File_Root = Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8, 2);
                Item_To_Complete.Web.AssocFilePath = Item_To_Complete.Web.File_Root + "\\" + Item_To_Complete.VID + "\\";

                //// Create the static html pages
                //string base_url = RequestSpecificValues.Current_Mode.Base_URL;
                //try
                //{
                //    Static_Pages_Builder staticBuilder = new Static_Pages_Builder(UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL, UI_ApplicationCache_Gateway.Settings.Servers.Base_Data_Directory, RequestSpecificValues.HTML_Skin.Skin_Code);
                //    if (!Directory.Exists(digitalResourceDirectory + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name))
                //        Directory.CreateDirectory(digitalResourceDirectory + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name);
                //    string filename = digitalResourceDirectory + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html";
                //    staticBuilder.Create_Item_Citation_HTML(Item_To_Complete, filename, String.Empty);

                //    // Copy the static HTML file to the web server
                //    try
                //    {
                //        if (!Directory.Exists(UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + RequestSpecificValues.Current_Item.BibID.Substring(0, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(2, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(4, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(6, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(8)))
                //            Directory.CreateDirectory(UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + RequestSpecificValues.Current_Item.BibID.Substring(0, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(2, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(4, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(6, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(8));
                //        if (File.Exists(filename))
                //            File.Copy(filename, UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + RequestSpecificValues.Current_Item.BibID.Substring(0, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(2, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(4, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(6, 2) + "\\" + RequestSpecificValues.Current_Item.BibID.Substring(8) + "\\" + RequestSpecificValues.Current_Item.BibID + "_" + RequestSpecificValues.Current_Item.VID + ".html", true);
                //    }
                //    catch (Exception)
                //    {
                //        // This is not critical
                //    }
                //}
                //catch (Exception)
                //{
                //}

                //RequestSpecificValues.Current_Mode.Base_URL = base_url;

                // Save the rest of the metadata
                Item_To_Complete.Save_SobekCM_METS();

                // Finally, set the RequestSpecificValues.Current_Item for more processing if there were any files
                if (((image_files.Count > 0) || (download_files.Count > 0)) && ( Item_To_Complete.Web.ItemID > 0 ))
                {
                    Database.SobekCM_Database.Update_Additional_Work_Needed_Flag(Item_To_Complete.Web.ItemID, true, Tracer);
                }
            }
            catch (Exception ee)
            {
                // Set an initial flag
                criticalErrorEncountered = true;

                string error_body = "<strong>ERROR ENCOUNTERED DURING ONLINE FILE MANAGEMENT</strong><br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a><br />User: "******"<br /><br /></blockquote>" + ee.ToString().Replace("\n", "<br />");
                string error_subject = "Error during file management for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                string email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Error_Email;
                if (email_to.Length == 0)
                    email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Email;
                Email_Helper.SendEmail(email_to, error_subject, error_body, true, String.Empty);
            }

            return criticalErrorEncountered;
        }
 /// <summary> Adds a file (with the appropriate divisions and pages) to this tree by filename  </summary>
 /// <param name="FileName"> Name of the file to add </param>
 /// <param name="Label"> Label for the page containing this file, if it is a new page </param>
 /// <returns> Newly built <see cref="SobekCM_File_Info" /> object which has been added to this tree </returns>
 /// <remarks> This is generally used to add just a single file.  To add many files, better logic should be implemented </remarks>
 public SobekCM_File_Info Add_File(string FileName, string Label)
 {
     SobekCM_File_Info newFile = new SobekCM_File_Info(FileName);
     Add_File(newFile, Label);
     return newFile;
 }
        /// <summary> Reads metadata from an open stream and saves to the provided item/package </summary>
        /// <param name="Input_Stream"> Open stream to read metadata from </param>
        /// <param name="Return_Package"> Package into which to read the metadata </param>
        /// <param name="Options"> Dictionary of any options which this metadata reader/writer may utilize </param>
        /// <param name="Error_Message">[OUTPUT] Explanation of the error, if an error occurs during reading </param>
        /// <returns>TRUE if successful, otherwise FALSE </returns>
        /// <remarks> Accepts two options: (1) 'METS_File_ReaderWriter:Minimize_File_Info' which tells whether the reader 
        /// should just skip the file reading portion completely, and just read the bibliographic data ( Default is FALSE).
        /// (2) 'METS_File_ReaderWriter:Support_Divisional_dmdSec_amdSec' </remarks>
        public bool Read_Metadata(Stream Input_Stream, SobekCM_Item Return_Package, Dictionary<string, object> Options, out string Error_Message)
        {
            Error_Message = String.Empty;

            // Read the options from the dictionary of options
            bool minimizeFileInfo = false;
            if (Options != null)
            {
                if (Options.ContainsKey("METS_File_ReaderWriter:Minimize_File_Info"))
                    bool.TryParse(Options["METS_File_ReaderWriter:Minimize_File_Info"].ToString(), out minimizeFileInfo);

                if (Options.ContainsKey("METS_File_ReaderWriter:Support_Divisional_dmdSec_amdSec"))
                {
                    bool supportDivisionalDmdSecAmdSec;
                    bool.TryParse(Options["METS_File_ReaderWriter:Support_Divisional_dmdSec_amdSec"].ToString(), out supportDivisionalDmdSecAmdSec);
                }
            }

            // Keep a list of all the files created, by file id, as additional data is gathered
            // from the different locations ( amdSec, fileSec, structmap )
            Dictionary<string, SobekCM_File_Info> files_by_fileid = new Dictionary<string, SobekCM_File_Info>();

            // For now, to do support for old way of doing downloads, build a list to hold
            // the deprecated download files
            List<Download_Info_DEPRECATED> deprecatedDownloads = new List<Download_Info_DEPRECATED>();

            // Need to store the unanalyzed sections of dmdSec and amdSec until we determine if 
            // the scope is the whole package, or the top-level div.  We use lists as the value since
            // several sections may have NO id and the METS may even (incorrectly) have multiple sections
            // with the same ID
            Dictionary<string, List<Unanalyzed_METS_Section>> dmdSec = new Dictionary<string, List<Unanalyzed_METS_Section>>();
            Dictionary<string, List<Unanalyzed_METS_Section>> amdSec = new Dictionary<string, List<Unanalyzed_METS_Section>>();

            // Dictionaries store the link between dmdSec and amdSec id's to single divisions
            Dictionary<string, abstract_TreeNode> division_dmdids = new Dictionary<string, abstract_TreeNode>();
            Dictionary<string, abstract_TreeNode> division_amdids = new Dictionary<string, abstract_TreeNode>();


            try
            {
                // Try to read the XML
                XmlReader r = new XmlTextReader(Input_Stream);

                // Begin stepping through each of the XML nodes
                while (r.Read())
                {
                    #region Handle some processing instructions requested by Florida SUS's / FLVC (hope to deprecate)

                    // Handle some processing instructions requested by Florida SUS's / FLVC
                    if (r.NodeType == XmlNodeType.ProcessingInstruction)
                    {
                        if (r.Name.ToLower() == "fcla")
                        {
                            string value = r.Value.ToLower();
                            if (value.IndexOf("fda=\"yes\"") >= 0)
                            {
                                DAITSS_Info daitssInfo = Return_Package.Get_Metadata_Module(GlobalVar.DAITSS_METADATA_MODULE_KEY) as DAITSS_Info;
                                if (daitssInfo == null)
                                {
                                    daitssInfo = new DAITSS_Info();
                                    Return_Package.Add_Metadata_Module(GlobalVar.DAITSS_METADATA_MODULE_KEY, daitssInfo);
                                }
                                daitssInfo.toArchive = true;
                            }
                            if (value.IndexOf("fda=\"no\"") >= 0)
                            {
                                DAITSS_Info daitssInfo2 = Return_Package.Get_Metadata_Module(GlobalVar.DAITSS_METADATA_MODULE_KEY) as DAITSS_Info;
                                if (daitssInfo2 == null)
                                {
                                    daitssInfo2 = new DAITSS_Info();
                                    Return_Package.Add_Metadata_Module(GlobalVar.DAITSS_METADATA_MODULE_KEY, daitssInfo2);
                                }
                                daitssInfo2.toArchive = false;
                            }
                        }
                    }

                    #endregion

                    if (r.NodeType == XmlNodeType.Element)
                    {
                        switch (r.Name.Replace("METS:", ""))
                        {
                            case "mets":
                                if (r.MoveToAttribute("OBJID"))
                                    Return_Package.METS_Header.ObjectID = r.Value;
                                break;

                            case "metsHdr":
                                read_mets_header(r.ReadSubtree(), Return_Package);
                                break;

                            case "dmdSec":
                            case "dmdSecFedora":
                                Unanalyzed_METS_Section thisDmdSec = store_dmd_sec(r.ReadSubtree());
                                if ( dmdSec.ContainsKey(thisDmdSec.ID))
                                    dmdSec[thisDmdSec.ID].Add(thisDmdSec);
                                else
                                {
                                    List<Unanalyzed_METS_Section> newDmdSecList = new List<Unanalyzed_METS_Section>();
                                    newDmdSecList.Add(thisDmdSec);
                                    dmdSec[thisDmdSec.ID] = newDmdSecList;
                                }
                                
                                break;

                            case "amdSec":
                                Unanalyzed_METS_Section thisAmdSec = store_amd_sec(r.ReadSubtree());
                                if (amdSec.ContainsKey(thisAmdSec.ID))
                                    amdSec[thisAmdSec.ID].Add(thisAmdSec);
                                else
                                {
                                    List<Unanalyzed_METS_Section> newAmdSecList = new List<Unanalyzed_METS_Section> {thisAmdSec};
                                    amdSec[thisAmdSec.ID] = newAmdSecList;
                                }
                                break;

                            case "fileSec":
                                read_file_sec(r.ReadSubtree(), minimizeFileInfo, files_by_fileid);
                                break;

                            case "structMap":
                                if (!r.IsEmptyElement)
                                {
                                    read_struct_map(r.ReadSubtree(), Return_Package, files_by_fileid, division_dmdids, division_amdids);
                                }
                                break;

                            case "behaviorSec":
                                read_behavior_sec(r.ReadSubtree(), Return_Package);
                                break;
                        }
                    }
                }

                // writer.Close();
                r.Close();

            }
            catch 
            {
                // Do nothinh
            }

            Input_Stream.Close();

            // Load some options for interoperability
            Dictionary<string, object> options = new Dictionary<string, object>();
            options.Add("SobekCM_FileInfo_METS_amdSec_ReaderWriter:Files_By_FileID", files_by_fileid);

            #region Process the previously stored dmd sections

            // Now, process the previously stored dmd sections
            foreach (string thisDmdSecId in dmdSec.Keys)
            {
                // Could be multiple stored sections with the same (or no) ID
                foreach (Unanalyzed_METS_Section metsSection in dmdSec[thisDmdSecId])
                {
                    XmlReader reader = XmlReader.Create(new StringReader(metsSection.Inner_XML));
                    string mdtype = String.Empty;
                    string othermdtype = String.Empty;
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            if (reader.Name.ToLower().Replace("mets:", "") == "mdwrap")
                            {

                                if (reader.MoveToAttribute("MDTYPE"))
                                    mdtype = reader.Value;
                                if (reader.MoveToAttribute("OTHERMDTYPE"))
                                    othermdtype = reader.Value;

                                // NOt crazy about this part, but sometimes people do not use the OTHERMDTYPE
                                // tag correctly, and just use the LABEL to differentiate the types
                                if ((mdtype == "OTHER") && (othermdtype.Length == 0) && (reader.MoveToAttribute("LABEL")))
                                    othermdtype = reader.Value;

                                // Now, determine if this was a division-level read, or a package-wide
                                if (division_dmdids.ContainsKey(thisDmdSecId))
                                {
                                    // Division level dmdSec
                                    // Get the division
                                    abstract_TreeNode node = division_dmdids[thisDmdSecId];

                                    // Get an appropriate reader from the metadata configuration
                                    iDivision_dmdSec_ReaderWriter rw = ResourceObjectSettings.MetadataConfig.Get_Division_DmdSec_ReaderWriter(mdtype, othermdtype);

                                    // Is this dmdSec analyzable? (i.e., did we find an appropriate reader/writer?)
                                    if (rw == null)
                                    {
                                        node.Add_Unanalyzed_DMDSEC(metsSection);
                                    }
                                    else
                                    {
                                        rw.Read_dmdSec(reader, node, options);
                                    }
                                }
                                else
                                {
                                    // Package-level dmdSec 
                                    // Get an appropriate reader from the metadata configuration
                                    iPackage_dmdSec_ReaderWriter rw = ResourceObjectSettings.MetadataConfig.Get_Package_DmdSec_ReaderWriter(mdtype, othermdtype);

                                    // Is this dmdSec analyzable? (i.e., did we find an appropriate reader/writer?)
                                    if (rw == null)
                                    {
                                        Return_Package.Add_Unanalyzed_DMDSEC(metsSection);
                                    }
                                    else
                                    {
                                        rw.Read_dmdSec(reader, Return_Package, options);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            #endregion

            #region Process the previously stored amd sections

            // Now, process the previously stored amd sections
            foreach (string thisAmdSecId in amdSec.Keys)
            {
                // Could be multiple stored sections with the same (or no) ID
                foreach (Unanalyzed_METS_Section metsSection in amdSec[thisAmdSecId])
                {
                    XmlReader reader = XmlReader.Create(new StringReader(metsSection.Inner_XML));
                    string mdtype = String.Empty;
                    string othermdtype = String.Empty;
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            if (reader.Name.ToLower().Replace("mets:", "") == "mdwrap")
                            {

                                if (reader.MoveToAttribute("MDTYPE"))
                                    mdtype = reader.Value;
                                if (reader.MoveToAttribute("OTHERMDTYPE"))
                                    othermdtype = reader.Value;

                                // Package-level amdSec 
                                // Get an appropriate reader from the metadata configuration
                                iPackage_amdSec_ReaderWriter rw = ResourceObjectSettings.MetadataConfig.Get_Package_AmdSec_ReaderWriter(mdtype, othermdtype);

                                // Is this amdSec analyzable? (i.e., did we find an appropriate reader/writer?)
                                if (rw == null)
                                {
                                    Return_Package.Add_Unanalyzed_AMDSEC(metsSection);
                                }
                                else
                                {
                                    rw.Read_amdSec(reader, Return_Package, options);
                                }
                            }
                        }
                    }
                }
            }

            #endregion

            #region Special code used for moving downloads into the structure map system, and out of the old SobekCM METS section 

            // For backward compatability, move from the old download system to the
            // new structure.  This has to happen here at the end so that we have access

            // Were there some downloads added here?
            if (deprecatedDownloads.Count > 0)
            {
                // Get the list of downloads from the download tree
                List<SobekCM_File_Info> newStructureDownloads = Return_Package.Divisions.Download_Tree.All_Files;

                // Step through each download in the old system
                foreach (Download_Info_DEPRECATED thisDownload in deprecatedDownloads)
                {
                    // Get the label (if there is one)
                    string label = thisDownload.Label;
                    string filename = thisDownload.FileName;
                    bool found = false;
                    if ((filename.Length == 0) && (thisDownload.File_ID.Length > 0))
                    {
                        if (files_by_fileid.ContainsKey(thisDownload.File_ID))
                        {
                            SobekCM_File_Info thisDownloadFile = files_by_fileid[thisDownload.File_ID];
                            filename = thisDownloadFile.System_Name;

                            // Ensure a file of this name doesn't already exist
                            foreach (SobekCM_File_Info existingFile in newStructureDownloads)
                            {
                                if (existingFile.System_Name.ToUpper().Trim() == filename.ToUpper().Trim())
                                {
                                    found = true;
                                    break;
                                }
                            }

                            // Not found, so add it
                            if (!found)
                            {
                                // Determine the label if it was missing or identical to file name
                                if ((label.Length == 0) || (label == filename))
                                {
                                    label = filename;
                                    int first_period_index = label.IndexOf('.');
                                    if (first_period_index > 0)
                                    {
                                        label = label.Substring(0, first_period_index);
                                    }
                                }

                                // Add the root to the download tree, if not existing
                                Division_TreeNode newRoot;
                                if (Return_Package.Divisions.Download_Tree.Roots.Count == 0)
                                {
                                    newRoot = new Division_TreeNode("Main", String.Empty);
                                    Return_Package.Divisions.Download_Tree.Roots.Add(newRoot);
                                }
                                else
                                {
                                    newRoot = (Division_TreeNode) Return_Package.Divisions.Download_Tree.Roots[0];
                                }

                                // Add a page for this, with the provided label if there was one
                                Page_TreeNode newPage = new Page_TreeNode(label);
                                newRoot.Nodes.Add(newPage);

                                // Now, add this existing file
                                newPage.Files.Add(thisDownloadFile);

                                // Add to the list of files added (in case it appears twice)
                                newStructureDownloads.Add(thisDownloadFile);
                            }
                        }
                    }
                    else
                    {
                        // Ensure a file of this name doesn't already exist
                        foreach (SobekCM_File_Info existingFile in newStructureDownloads)
                        {
                            if (existingFile.System_Name.ToUpper().Trim() == filename.ToUpper().Trim())
                            {
                                found = true;
                                break;
                            }
                        }

                        // Not found, so add it
                        if (!found)
                        {
                            // Determine the label if it was missing or identical to file name
                            if ((label.Length == 0) || (label == filename))
                            {
                                label = filename;
                                int first_period_index = label.IndexOf('.');
                                if (first_period_index > 0)
                                {
                                    label = label.Substring(0, first_period_index);
                                }
                            }

                            // Add the root to the download tree, if not existing
                            Division_TreeNode newRoot;
                            if (Return_Package.Divisions.Download_Tree.Roots.Count == 0)
                            {
                                newRoot = new Division_TreeNode("Main", String.Empty);
                                Return_Package.Divisions.Download_Tree.Roots.Add(newRoot);
                            }
                            else
                            {
                                newRoot = (Division_TreeNode) Return_Package.Divisions.Download_Tree.Roots[0];
                            }

                            // Add a page for this, with the provided label if there was one
                            Page_TreeNode newPage = new Page_TreeNode(label);
                            newRoot.Nodes.Add(newPage);

                            // Now, add this existing file
                            SobekCM_File_Info thisDownloadFile = new SobekCM_File_Info(filename);
                            newPage.Files.Add(thisDownloadFile);

                            // Add to the list of files added (in case it appears twice)
                            newStructureDownloads.Add(thisDownloadFile);
                        }
                    }
                }
            }

            #endregion

            #region Special code for distributing any page-level coordinate information read from the old SobekCM coordinate metadata

            // Get the geospatial data
            GeoSpatial_Information geoSpatial = Return_Package.Get_Metadata_Module(GlobalVar.GEOSPATIAL_METADATA_MODULE_KEY) as GeoSpatial_Information;
            if ((geoSpatial != null) && ( geoSpatial.Polygon_Count > 0 ))
            {
                // See if any has the page sequence filled out, which means it came from the old metadata system
                bool redistribute = false;
                foreach (Coordinate_Polygon thisPolygon in geoSpatial.Polygons)
                {
                    if (thisPolygon.Page_Sequence > 0)
                    {
                        redistribute = true;
                        break;
                    }
                }

                // If we need to redistribute, get started!
                if (redistribute)
                {
                    // Get the pages, by sequence
                    List<abstract_TreeNode> pagesBySequence = Return_Package.Divisions.Physical_Tree.Pages_PreOrder;
                    List<Coordinate_Polygon> polygonsToRemove = new List<Coordinate_Polygon>();

                    // Step through each polygon
                    foreach (Coordinate_Polygon thisPolygon in geoSpatial.Polygons)
                    {
                        if ((thisPolygon.Page_Sequence > 0) && ( thisPolygon.Page_Sequence <= pagesBySequence.Count ))
                        {
                            // Get the page
                            abstract_TreeNode thisPageFromSequence = pagesBySequence[thisPolygon.Page_Sequence - 1];

                            // We can assume this page does not already have the coordiantes
                            GeoSpatial_Information thisPageCoord = new GeoSpatial_Information();
                            thisPageFromSequence.Add_Metadata_Module( GlobalVar.GEOSPATIAL_METADATA_MODULE_KEY, thisPageCoord );
                            thisPageCoord.Add_Polygon( thisPolygon);

                            // Remove this from the package-level coordinates
                            polygonsToRemove.Add(thisPolygon);
                        }
                    }

                    // Now, remove all polygons flagged to be removed
                    foreach (Coordinate_Polygon thisPolygon in polygonsToRemove)
                    {
                        geoSpatial.Remove_Polygon(thisPolygon);
                    }
                }
            }

            #endregion

            #region Copy any serial hierarchy in the Behaviors.Serial_Info part into the bib portion, if not there

            // Do some final cleanup on the SERIAL HIERARCHY
            if ((Return_Package.Behaviors.hasSerialInformation) && (Return_Package.Behaviors.Serial_Info.Count > 0))
            {
                if ((Return_Package.Bib_Info.Series_Part_Info.Enum1.Length == 0) && (Return_Package.Bib_Info.Series_Part_Info.Year.Length == 0))
                {
                    if (Return_Package.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.Newspaper)
                    {
                        Return_Package.Bib_Info.Series_Part_Info.Year = Return_Package.Behaviors.Serial_Info[0].Display;
                        Return_Package.Bib_Info.Series_Part_Info.Year_Index = Return_Package.Behaviors.Serial_Info[0].Order;

                        if (Return_Package.Behaviors.Serial_Info.Count > 1)
                        {
                            Return_Package.Bib_Info.Series_Part_Info.Month = Return_Package.Behaviors.Serial_Info[1].Display;
                            Return_Package.Bib_Info.Series_Part_Info.Month_Index = Return_Package.Behaviors.Serial_Info[1].Order;
                        }
                    }

                    if (Return_Package.Behaviors.Serial_Info.Count > 2)
                    {
                        Return_Package.Bib_Info.Series_Part_Info.Day = Return_Package.Behaviors.Serial_Info[2].Display;
                        Return_Package.Bib_Info.Series_Part_Info.Day_Index = Return_Package.Behaviors.Serial_Info[2].Order;
                    }
                }
                else
                {
                    Return_Package.Bib_Info.Series_Part_Info.Enum1 = Return_Package.Behaviors.Serial_Info[0].Display;
                    Return_Package.Bib_Info.Series_Part_Info.Enum1_Index = Return_Package.Behaviors.Serial_Info[0].Order;

                    if (Return_Package.Behaviors.Serial_Info.Count > 1)
                    {
                        Return_Package.Bib_Info.Series_Part_Info.Enum2 = Return_Package.Behaviors.Serial_Info[1].Display;
                        Return_Package.Bib_Info.Series_Part_Info.Enum2_Index = Return_Package.Behaviors.Serial_Info[1].Order;
                    }

                    if (Return_Package.Behaviors.Serial_Info.Count > 2)
                    {
                        Return_Package.Bib_Info.Series_Part_Info.Enum3 = Return_Package.Behaviors.Serial_Info[2].Display;
                        Return_Package.Bib_Info.Series_Part_Info.Enum3_Index = Return_Package.Behaviors.Serial_Info[2].Order;
                    }
                }
            }

            #endregion

            return true;
        }
 /// <summary> Adds a file  object (with the appropriate divisions and pages) to this tree </summary>
 /// <param name="New_File"> New file object to add </param>
 /// <remarks> This is generally used to add just a single file.  To add many files, better logic should be implemented </remarks>
 public void Add_File(SobekCM_File_Info New_File)
 {
     Add_File(New_File, String.Empty);
 }
        private bool complete_item_submission(SobekCM_Item Item_To_Complete, Custom_Tracer Tracer )
        {
            // Set an initial flag
            criticalErrorEncountered = false;

            string final_destination = Item_To_Complete.Source_Directory;

            string[] image_files = Directory.GetFiles(digitalResourceDirectory);

            // This package is good to go, so build it, save, etc...
            try
            {
                // Step through each file
                bool error_reading_file_occurred = false;

                // Add the SourceImage files first
                bool jpeg_added = false;
                bool jp2_added = false;
                foreach (string thisFile in image_files)
                {
                    // Create the new file object and compute a label
                    FileInfo fileInfo = new FileInfo(thisFile);
                    SobekCM_File_Info newFile = new SobekCM_File_Info(fileInfo.Name);

                    // Copy this file
                    File.Copy(thisFile, final_destination + "\\" + fileInfo.Name, true);
                    RequestSpecificValues.Current_Item.Divisions.Physical_Tree.Add_File(newFile, "New Page");

                    // Seperate code for JP2 and JPEG type files
                    string extension = fileInfo.Extension.ToUpper();
                    if (extension.IndexOf("JP2") >= 0)
                    {
                        if (!error_reading_file_occurred)
                        {
                            if (!newFile.Compute_Jpeg2000_Attributes(RequestSpecificValues.Current_Item.Source_Directory))
                                error_reading_file_occurred = true;
                        }
                        jp2_added = true;
                    }
                    else if (extension.IndexOf("JPG") >= 0)
                    {
                        if (!error_reading_file_occurred)
                        {
                            if (!newFile.Compute_Jpeg_Attributes(RequestSpecificValues.Current_Item.Source_Directory))
                                error_reading_file_occurred = true;
                        }
                        jpeg_added = true;
                    }
                }

                // Add the JPEG2000 and JPEG-specific viewers
                //RequestSpecificValues.Current_Item.Behaviors.Clear_Views();
                if (jpeg_added)
                {
                    // Is a JPEG view already existing?
                    bool jpeg_viewer_already_exists = false;
                    foreach (View_Object thisViewer in RequestSpecificValues.Current_Item.Behaviors.Views)
                    {
                        if (thisViewer.View_Type == View_Enum.JPEG)
                        {
                            jpeg_viewer_already_exists = true;
                            break;
                        }
                    }

                    // Add the JPEG view if it did not already exists
                    if ( !jpeg_viewer_already_exists )
                        RequestSpecificValues.Current_Item.Behaviors.Add_View(View_Enum.JPEG);
                }

                // If a JPEG2000 file was just added, ensure it exists as a view for this RequestSpecificValues.Current_Item
                if (jp2_added)
                {
                    // Is a JPEG view already existing?
                    bool jpg2000_viewer_already_exists = false;
                    foreach (View_Object thisViewer in RequestSpecificValues.Current_Item.Behaviors.Views)
                    {
                        if (thisViewer.View_Type == View_Enum.JPEG2000 )
                        {
                            jpg2000_viewer_already_exists = true;
                            break;
                        }
                    }

                    // Add the JPEG2000 view if it did not already exists
                    if (!jpg2000_viewer_already_exists)
                        RequestSpecificValues.Current_Item.Behaviors.Add_View(View_Enum.JPEG2000);
                }

                // Determine the total size of the package before saving
                string[] all_files_final = Directory.GetFiles(final_destination);
                double size = all_files_final.Aggregate<string, double>(0, (Current, ThisFile) => Current + (((new FileInfo(ThisFile)).Length)/1024));
                Item_To_Complete.DiskSize_KB = size;

                // Create the options dictionary used when saving information to the database, or writing MarcXML
                Dictionary<string, object> options = new Dictionary<string, object>();
                if (UI_ApplicationCache_Gateway.Settings.MarcGeneration != null)
                {
                    options["MarcXML_File_ReaderWriter:MARC Cataloging Source Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Cataloging_Source_Code;
                    options["MarcXML_File_ReaderWriter:MARC Location Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Location_Code;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Agency"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Agency;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Place"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Place;
                    options["MarcXML_File_ReaderWriter:MARC XSLT File"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.XSLT_File;
                }
                options["MarcXML_File_ReaderWriter:System Name"] = UI_ApplicationCache_Gateway.Settings.System.System_Name;
                options["MarcXML_File_ReaderWriter:System Abbreviation"] = UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation;

                // Save to the database
                try
                {
                    SobekCM_Database.Save_Digital_Resource(Item_To_Complete, options);
                }
                catch (Exception ee)
                {
                    StreamWriter writer = new StreamWriter(digitalResourceDirectory + "\\exception.txt", false);
                    writer.WriteLine( "ERROR CAUGHT WHILE SAVING DIGITAL RESOURCE");
                    writer.WriteLine( DateTime.Now.ToString());
                    writer.WriteLine();
                    writer.WriteLine( ee.Message );
                    writer.WriteLine( ee.StackTrace );
                    writer.Flush();
                    writer.Close();
                    throw;
                }

                // Assign the file root and assoc file path
                Item_To_Complete.Web.File_Root = Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8, 2);
                Item_To_Complete.Web.AssocFilePath = Item_To_Complete.Web.File_Root + "\\" + Item_To_Complete.VID + "\\";

                // Save the rest of the metadata
                Item_To_Complete.Save_SobekCM_METS();

                // Finally, set the RequestSpecificValues.Current_Item for more processing if there were any files
                if ((image_files.Length > 0) && ( Item_To_Complete.Web.ItemID > 0 ))
                {
                    Database.SobekCM_Database.Update_Additional_Work_Needed_Flag(Item_To_Complete.Web.ItemID, true, Tracer);
                }

                foreach (string thisFile in image_files)
                {
                    try
                    {
                        File.Delete(thisFile);
                    }
                    catch
                    {
                        // Do nothing - not a fatal problem
                    }
                }

                try
                {
                    Directory.Delete(digitalResourceDirectory);
                }
                catch
                {
                    // Do nothing - not a fatal problem
                }

                // This may be called from QC, so check on that as well
                string userInProcessDirectory = UI_ApplicationCache_Gateway.Settings.Servers.In_Process_Submission_Location + "\\" + RequestSpecificValues.Current_User.UserName.Replace(".", "").Replace("@", "") + "\\qcwork\\" + Item_To_Complete.METS_Header.ObjectID;
                if (RequestSpecificValues.Current_User.ShibbID.Trim().Length > 0)
                    userInProcessDirectory = UI_ApplicationCache_Gateway.Settings.Servers.In_Process_Submission_Location + "\\" + RequestSpecificValues.Current_User.ShibbID + "\\qcwork\\" + Item_To_Complete.METS_Header.ObjectID;

                // Make the folder for the RequestSpecificValues.Current_User in process directory
                if (Directory.Exists(userInProcessDirectory))
                {
                    foreach (string thisFile in Directory.GetFiles(userInProcessDirectory))
                    {
                        try
                        {
                            File.Delete(thisFile);
                        }
                        catch
                        {
                            // Do nothing - not a fatal problem
                        }
                    }
                }
                HttpContext.Current.Session[Item_To_Complete.BibID + "_" + Item_To_Complete.VID + " QC Work"] = null;

            }
            catch (Exception ee)
            {
                // Set an initial flag
                criticalErrorEncountered = true;

                string error_body = "<strong>ERROR ENCOUNTERED DURING ONLINE PAGE IMAGE UPLOAD</strong><br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + RequestSpecificValues.Current_Mode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a><br />RequestSpecificValues.Current_User: "******"<br /><br /></blockquote>" + ee.ToString().Replace("\n", "<br />");
                string error_subject = "Error during file management for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                string email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Error_Email;
                if (email_to.Length == 0)
                    email_to = UI_ApplicationCache_Gateway.Settings.Email.System_Email;
                Email_Helper.SendEmail(email_to, error_subject, error_body, true, String.Empty);
            }

            return criticalErrorEncountered;
        }
        /// <summary> Adds a file  object (with the appropriate divisions and pages) to this tree </summary>
        /// <param name="New_File"> New file object to add </param>
        /// <param name="Label"> Label for the page containing this file, if it is a new page </param>
        /// <remarks> This is generally used to add just a single file.  To add many files, better logic should be implemented </remarks>
        public void Add_File(SobekCM_File_Info New_File, string Label)
        {
            // Determine the upper case name
            string systemname_upper = New_File.File_Name_Sans_Extension;

            // Look for a page/entity which has the same file name, else it will be added to the last division
            foreach (abstract_TreeNode rootNode in Roots)
            {
                if (recursively_add_file(rootNode, New_File, systemname_upper))
                {
                    return;
                }
            }

            // If not found, find the last division
            if (Roots.Count > 0)
            {
                if (!Roots[Roots.Count - 1].Page)
                {
                    // Get his last division
                    Division_TreeNode lastDivision = (Division_TreeNode) Roots[Roots.Count - 1];

                    // Find the last division then
                    while ((lastDivision.Nodes.Count > 0) && (!lastDivision.Nodes[lastDivision.Nodes.Count - 1].Page))
                    {
                        lastDivision = (Division_TreeNode) lastDivision.Nodes[lastDivision.Nodes.Count - 1];
                    }

                    // Add this as a new page on the last division
                    Page_TreeNode newPage = new Page_TreeNode(Label);
                    lastDivision.Add_Child(newPage);

                    // Now, add this file to the page
                    newPage.Files.Add(New_File);
                }
                else
                {
                    // No divisions at all, but pages exist at the top level, which is okay
                    Page_TreeNode pageNode = (Page_TreeNode) Roots[Roots.Count - 1];

                    // Now, add this file to the page
                    pageNode.Files.Add(New_File);
                }
            }
            else
            {
                // No nodes exist, so add a MAIN division node
                Division_TreeNode newDivNode = new Division_TreeNode("Main", String.Empty);
                Roots.Add(newDivNode);

                // Add this as a new page on the new division
                Page_TreeNode newPage = new Page_TreeNode(Label);
                newDivNode.Add_Child(newPage);

                // Now, add this file to the page
                newPage.Files.Add(New_File);
            }
        }
Exemplo n.º 23
0
        /// <summary> Finalize this METS file for the lsat writing before loading to SobekCM </summary>
        /// <param name="calculateAllChecksums">Flag indicates if all checksums should be recalculated</param>
        /// <returns>TRUE if successful, otherwise FALSE</returns>
        public bool Finalize_METS(bool calculateAllChecksums)
        {
            try
            {
                // Build the collections to hold all the file information
                Dictionary<string, Page_TreeNode> allFiles = new Dictionary<string, Page_TreeNode>();
                Dictionary<string, SobekCM_File_Info> jpegFiles = new Dictionary<string, SobekCM_File_Info>();
                Dictionary<string, SobekCM_File_Info> tiffFiles = new Dictionary<string, SobekCM_File_Info>();
                Dictionary<string, SobekCM_File_Info> jp2Files = new Dictionary<string, SobekCM_File_Info>();
                Dictionary<string, SobekCM_File_Info> textFiles = new Dictionary<string, SobekCM_File_Info>();
                Dictionary<string, SobekCM_File_Info> proFiles = new Dictionary<string, SobekCM_File_Info>();

                // Step through each file in the division section of the METS
                string name;
                List<abstract_TreeNode> packagePages = Divisions.Physical_Tree.Pages_PreOrder;
                foreach (Page_TreeNode thisPage in packagePages)
                {
                    foreach (SobekCM_File_Info thisFile in thisPage.Files)
                    {
                        // Make sure the name is long enough
                        if (thisFile.System_Name.Length < 1)
                        {
                            throw new Exception("FILE NAME IN METS IS NOT VALID");
                        }

                        // Calculate the name
                        name = thisFile.File_Name_Sans_Extension;
                        string fullname = thisFile.System_Name.ToUpper();

                        // Is this a text file?
                        if (fullname.IndexOf(".TXT") > 0)
                        {
                            textFiles[name] = thisFile;

                            // Always recalculate the checksums for the text files
                            thisFile.Checksum = String.Empty;
                            thisFile.Size = -1;
                        }

                        // Is this a jpeg file?
                        if (fullname.IndexOf(".JPG") > 0)
                        {
                            jpegFiles[name] = thisFile;
                        }

                        // Is this a TIFF file?
                        if (fullname.IndexOf(".TIF") > 0)
                        {
                            tiffFiles[name] = thisFile;
                        }

                        // Is this a jpeg2000 file?
                        if (fullname.IndexOf(".JP2") > 0)
                        {
                            jp2Files[name] = thisFile;
                        }

                        // Is this a PRO file?
                        if (fullname.IndexOf(".PRO") > 0)
                        {
                            proFiles[name] = thisFile;
                        }

                        // Add the page by name
                        allFiles[name] = thisPage;

                        // Should all files have their checksum cleared?
                        if (calculateAllChecksums)
                        {
                            thisFile.Checksum = String.Empty;
                            thisFile.Size = -1;
                        }
                    }
                }

                // Now, step through each text file in the METS package directory
                string[] textFilesInDir = Directory.GetFiles(Source_Directory, "*.txt");
                string shortName;
                foreach (string thisTextFile in textFilesInDir)
                {
                    // Get the name
                    name = (new FileInfo(thisTextFile).Name);
                    shortName = File_Name_Sans_Extension(name);

                    // Was there any link to this file name, and no text in the METS?
                    if ((allFiles.ContainsKey(shortName)) && (!textFiles.ContainsKey(shortName)))
                    {
                        // Create the new file object
                        SobekCM_File_Info thisFile = new SobekCM_File_Info(name);

                        // Add to the page
                        allFiles[shortName].Files.Add(thisFile);
                    }
                }

                // Now, step through each PRO file in the METS package directory
                string[] proFilesInDir = Directory.GetFiles(Source_Directory, "*.pro");
                foreach (string thisProFile in proFilesInDir)
                {
                    // Get the name
                    name = (new FileInfo(thisProFile).Name);
                    shortName = File_Name_Sans_Extension(name);

                    // Was there any link to this file name, and no PRO in the METS?
                    if ((allFiles.ContainsKey(shortName)) && (!proFiles.ContainsKey(shortName)))
                    {
                        // Create the new file object
                        SobekCM_File_Info thisFile = new SobekCM_File_Info(name);

                        // Add to the page
                        allFiles[shortName].Files.Add(thisFile);
                    }
                }

                // Now, step through each jpeg file in the METS package directory
                bool allHaveThumbs = true;
                textFilesInDir = Directory.GetFiles(Source_Directory, "*.jpg");
                foreach (string thisTextFile in textFilesInDir)
                {
                    if ((thisTextFile.ToUpper().IndexOf("QC.JPG") < 0) && (thisTextFile.ToUpper().IndexOf("QC2.JPG") < 0) && (thisTextFile.ToUpper().IndexOf("THM.JPG") < 0))
                    {
                        // Get the name
                        name = (new FileInfo(thisTextFile).Name);
                        shortName = File_Name_Sans_Extension(name);

                        // Does a JPEG Thumbnail exist as well?
                        if ((allHaveThumbs) && (!File.Exists(Source_Directory + "\\" + name.Replace(".jpg", "thm.jpg"))))
                        {
                            allHaveThumbs = false;
                        }

                        // Was there any link to this file name, and no jpeg in the METS?
                        if ((allFiles.ContainsKey(shortName)) && (!jpegFiles.ContainsKey(shortName)))
                        {
                            // Create the new file object
                            SobekCM_File_Info thisFile = new SobekCM_File_Info(name);

                            // Add to the page
                            allFiles[shortName].Files.Add(thisFile);
                        }
                    }
                }

                // Set the related image, if they all had thumbnails
                if (allHaveThumbs)
                {
                    bool relatedAlreadyThere = Behaviors.Views.Any(thisView => thisView.View_Type == View_Enum.RELATED_IMAGES);

                    if (!relatedAlreadyThere)
                    {
                        Behaviors.Add_View(View_Enum.RELATED_IMAGES);
                    }
                }

                // Now, step through each jpeg2000 file in the METS package directory
                allHaveThumbs = true;
                textFilesInDir = Directory.GetFiles(Source_Directory, "*.jp2");
                foreach (string thisTextFile in textFilesInDir)
                {
                    // Get the name
                    name = (new FileInfo(thisTextFile).Name);
                    shortName = File_Name_Sans_Extension(name);

                    // Does a JPEG Thumbnail exist as well?
                    if ((allHaveThumbs) && (!File.Exists(Source_Directory + "\\" + name.Replace(".jp2", "thm.jpg"))))
                    {
                        allHaveThumbs = false;
                    }

                    // Was there any link to this file name, and no jpeg2000 in the METS?
                    if ((allFiles.ContainsKey(shortName)) && (!jp2Files.ContainsKey(shortName)))
                    {
                        // Create the new file object
                        SobekCM_File_Info thisFile = new SobekCM_File_Info(name);

                        // Add to the page
                        allFiles[shortName].Files.Add(thisFile);
                    }
                }

                // Set the related image, if they all had thumbnails
                if (allHaveThumbs)
                {
                    bool relatedAlreadyThere2 = Behaviors.Views.Any(thisView => thisView.View_Type == View_Enum.RELATED_IMAGES);

                    if (!relatedAlreadyThere2)
                    {
                        Behaviors.Add_View(View_Enum.RELATED_IMAGES);
                    }
                }

                //// If there is one thumbnail, assign it
                //int fileid = 999999;
                //string[] thumbs = Directory.GetFiles( Source_Directory, "*thm.jpg" );
                //if ( thumbs.Length >= 1 )
                //{
                //    string thumbname = ( new FileInfo( thumbs[0] )).Name;

                //    // Assign this file to the main thumbnail metadata field
                //    this.procParam.Main_Thumbnail = thumbname;

                //    Divisions.SobekCM_File_Info thumbFile = this.Divisions.File_By_System_Name(thumbname);

                //    // Also make sure this is in the file section
                //    if ( thumbFile == null )
                //    {
                //        this.Divisions.Add_File( fileid.ToString(), thumbname, String.Empty );
                //        fileid--;
                //    }
                //}

                // Save the old METS
                string[] metsFiles = Directory.GetFiles(Source_Directory, "*.mets*");
                if (metsFiles.Length == 1)
                {
                    try
                    {
                        File.Move(metsFiles[0], metsFiles[0] + ".bak");
                    }
                    catch
                    {
                    }
                }

                // Now, Write the METS file again
                Save_METS();

                // Finally, validate it
                bool returnValue = Validate_Against_Schema();
                if (!returnValue)
                {
                    finalizeErrors = validationErrors;
                }
                else
                {
                    finalizeErrors = String.Empty;
                }
                return returnValue;
            }
            catch (Exception ee)
            {
                finalizeErrors = ee.ToString();
                return false;
            }
        }
        private bool recursively_add_file(abstract_TreeNode Node, SobekCM_File_Info New_File, string SystemName_Upper)
        {
            // If this is a page, check for a match first
            if (Node.Page)
            {
                Page_TreeNode pageNode = (Page_TreeNode) Node;
                if (pageNode.Files.Count >= 1)
                {
                    if (pageNode.Files[0].File_Name_Sans_Extension == SystemName_Upper)
                    {
                        // Belongs to this page.  Now, just make sure it doesn't already exist
                        foreach (SobekCM_File_Info thisFile in pageNode.Files)
                        {
                            if (thisFile.System_Name.ToUpper() == New_File.System_Name.ToUpper())
                                return true;
                        }

                        // Not found, so add it to this page
                        pageNode.Files.Add(New_File);
                        return true;
                    }
                }
            }

            // If this was a division, check all pages
            if (!Node.Page)
            {
                Division_TreeNode divNode = (Division_TreeNode) Node;
                foreach (abstract_TreeNode childNodes in divNode.Nodes)
                {
                    if (recursively_add_file(childNodes, New_File, SystemName_Upper))
                    {
                        return true;
                    }
                }
            }

            // If nothing found that matches under this node, return false
            return false;
        }
        /// <summary> Create a test digital resource item  </summary>       
        /// <param name="directory">Directory for the package source directory</param>
        /// <returns>Fully built test bib package</returns>
        public static SobekCM_Item Create(string directory)
        {
            SobekCM_Item testPackage = new SobekCM_Item();

            // Add all the METS header information
            testPackage.METS_Header.Create_Date = new DateTime(2007, 1, 1);
            testPackage.METS_Header.Modify_Date = DateTime.Now;
            testPackage.METS_Header.Creator_Individual = "Mark Sullivan";
            testPackage.METS_Header.Add_Creator_Individual_Notes("Programmer of new SobekCM.Resource_Object");
            testPackage.METS_Header.Add_Creator_Individual_Notes("Adding coordinates");
            testPackage.METS_Header.Creator_Organization = "University of Florida";
            testPackage.METS_Header.Creator_Software = "SobekCM Bib Package Test";
            testPackage.METS_Header.RecordStatus_Enum = METS_Record_Status.COMPLETE;
            testPackage.METS_Header.Add_Creator_Org_Notes("This test package was done to test DLCs new METS package");

            // Add all the MODS elements
            Abstract_Info testAbstract = testPackage.Bib_Info.Add_Abstract("This is a sample abstract", "en");
            testPackage.Bib_Info.Add_Abstract("Tämä on esimerkki abstrakteja", "fin");
            testAbstract.Display_Label = "Summary Abstract";
            testAbstract.Type = "summary";

            testPackage.Bib_Info.Access_Condition.Text = "All rights are reserved by source institution.";
            testPackage.Bib_Info.Access_Condition.Language = "en";
            testPackage.Bib_Info.Access_Condition.Type = "restrictions on use";
            testPackage.Bib_Info.Access_Condition.Display_Label = "Rights";

            testPackage.Bib_Info.Add_Identifier("000123234", "OCLC", "Electronic OCLC");
            testPackage.Bib_Info.Add_Identifier("182-asdsd-28k", "DOI");

            testPackage.Bib_Info.Add_Language("English", String.Empty, "en");
            testPackage.Bib_Info.Add_Language("Finnish");
            testPackage.Bib_Info.Add_Language(String.Empty, "ita", String.Empty);

            testPackage.Bib_Info.Location.Holding_Code = "MVS";
            testPackage.Bib_Info.Location.Holding_Name = "From the Private Library of Mark Sullivan";
            testPackage.Bib_Info.Location.PURL = "http://www.uflib.ufl.edu/ufdc/?b=CA00000000";
            testPackage.Bib_Info.Location.Other_URL = "http://www.fnhm.edu";
            testPackage.Bib_Info.Location.Other_URL_Display_Label = "Specimen Information";
            testPackage.Bib_Info.Location.Other_URL_Note = "Specimen FLAS 125342 Database";
            testPackage.Bib_Info.Location.EAD_URL = "http://digital.uflib.ufl.edu/";
            testPackage.Bib_Info.Location.EAD_Name = "Digital Library Center Finding Guide";

            testPackage.Bib_Info.Main_Entity_Name.Name_Type = Name_Info_Type_Enum.Personal;
            testPackage.Bib_Info.Main_Entity_Name.Full_Name = "Brown, B.F.";
            testPackage.Bib_Info.Main_Entity_Name.Terms_Of_Address = "Dr.";
            testPackage.Bib_Info.Main_Entity_Name.Display_Form = "B.F. Brown";
            testPackage.Bib_Info.Main_Entity_Name.Affiliation = "Chemistry Dept., American University";
            testPackage.Bib_Info.Main_Entity_Name.Description = "Chemistry Professor Emeritus";
            testPackage.Bib_Info.Main_Entity_Name.Add_Role("Author");

            Zoological_Taxonomy_Info taxonInfo = new Zoological_Taxonomy_Info();
            testPackage.Add_Metadata_Module(GlobalVar.ZOOLOGICAL_TAXONOMY_METADATA_MODULE_KEY, taxonInfo);
            taxonInfo.Scientific_Name = "Ctenomys sociabilis";
            taxonInfo.Higher_Classification = "Animalia; Chordata; Vertebrata; Mammalia; Theria; Eutheria; Rodentia; Hystricognatha; Hystricognathi; Ctenomyidae; Ctenomyini; Ctenomys";
            taxonInfo.Kingdom = "Animalia";
            taxonInfo.Phylum = "Chordata";
            taxonInfo.Class = "Mammalia";
            taxonInfo.Order = "Rodentia";
            taxonInfo.Family = "Ctenomyidae";
            taxonInfo.Genus = "Ctenomys";
            taxonInfo.Specific_Epithet = "sociabilis";
            taxonInfo.Taxonomic_Rank = "species";
            taxonInfo.Common_Name = "Social Tuco-Tuco";

            Name_Info name1 = new Name_Info();
            name1.Name_Type = Name_Info_Type_Enum.Personal;
            name1.Given_Name = "John Paul";
            name1.Terms_Of_Address = "Pope; II";
            name1.Dates = "1920-2002";
            name1.User_Submitted = true;
            testPackage.Bib_Info.Add_Named_Entity(name1);

            Name_Info name2 = new Name_Info();
            name2.Name_Type = Name_Info_Type_Enum.Conference;
            name2.Full_Name = "Paris Peace Conference (1919-1920)";
            name2.Dates = "1919-1920";
            testPackage.Bib_Info.Add_Named_Entity(name2);

            Name_Info name3 = new Name_Info();
            name3.Name_Type = Name_Info_Type_Enum.Corporate;
            name3.Full_Name = "United States -- Court of Appeals (2nd Court)";
            testPackage.Bib_Info.Add_Named_Entity(name3);

            Name_Info name4 = new Name_Info();
            name4.Name_Type = Name_Info_Type_Enum.Personal;
            name4.Full_Name = "Wilson, Mary";
            name4.Display_Form = "Mary 'Weels' Wilson";
            name4.Given_Name = "Mary";
            name4.Family_Name = "Wilson";
            name4.ID = "NAM4";
            name4.Terms_Of_Address = "2nd";
            name4.Add_Role("illustrator");
            name4.Add_Role("cartographer");
            testPackage.Bib_Info.Add_Named_Entity(name4);

            Name_Info donor = new Name_Info();
            donor.Name_Type = Name_Info_Type_Enum.Personal;
            donor.Full_Name = "Livingston, Arthur";
            donor.Description = "Gift in honor of Arthur Livingston";
            donor.Terms_Of_Address = "3rd";
            donor.Add_Role("honoree", String.Empty);
            testPackage.Bib_Info.Donor = donor;

            testPackage.Bib_Info.Main_Title.NonSort = "The ";
            testPackage.Bib_Info.Main_Title.Title = "Man Who Would Be King";
            testPackage.Bib_Info.Main_Title.Subtitle = "The story of succession in England";

            Title_Info title1 = new Title_Info("homme qui voulut être roi", Title_Type_Enum.Translated);
            title1.NonSort = "L'";
            title1.Language = "fr";
            testPackage.Bib_Info.Add_Other_Title(title1);

            Title_Info title2 = new Title_Info();
            title2.Title = "Man Who Be King";
            title2.Display_Label = "also known as";
            title2.NonSort = "The";
            title2.Title_Type = Title_Type_Enum.Alternative;
            testPackage.Bib_Info.Add_Other_Title(title2);

            Title_Info title3 = new Title_Info();
            title3.Title = "Great works of England";
            title3.Authority = "naf";
            title3.Add_Part_Name("Second Portion");
            title3.Add_Part_Number("2nd");
            title3.Title_Type = Title_Type_Enum.Uniform;
            title3.User_Submitted = true;
            testPackage.Bib_Info.Add_Other_Title(title3);

            testPackage.Bib_Info.Add_Note("Funded by the NEH", Note_Type_Enum.Funding);
            testPackage.Bib_Info.Add_Note("Based on a play which originally appeared in France as \"Un peu plus tard, un peu plus tôt\"").User_Submitted = true;
            testPackage.Bib_Info.Add_Note("Anne Baxter (Louise), Maria Perschy (Angela), Gustavo Rojo (Bill), Reginald Gilliam (Mr. Johnson), [Catherine Elliot?] (Aunt Sallie), Ben Tatar (waiter)", Note_Type_Enum.Performers, "Performed By");

            testPackage.Bib_Info.Origin_Info.Add_Place("New York", "nyu", "usa");
            testPackage.Bib_Info.Origin_Info.Date_Issued = "1992";
            testPackage.Bib_Info.Origin_Info.MARC_DateIssued_Start = "1992";
            testPackage.Bib_Info.Origin_Info.MARC_DateIssued_End = "1993";
            testPackage.Bib_Info.Origin_Info.Date_Copyrighted = "1999";
            testPackage.Bib_Info.Origin_Info.Edition = "2nd";

            Publisher_Info newPub = testPackage.Bib_Info.Add_Publisher("Published for the American Vacuum Society by the American Institute of Physics");
            newPub.Add_Place("New York, New York");
            newPub.User_Submitted = true;
            testPackage.Bib_Info.Add_Publisher("University of Florida Press House").Add_Place("Gainesville, FL");
            testPackage.Bib_Info.Add_Manufacturer("Addison Randly Publishing House");

            testPackage.Bib_Info.Original_Description.Extent = "1 sound disc (56 min.) : digital ; 3/4 in.";
            testPackage.Bib_Info.Original_Description.Add_Note("The sleeve of this sound disc was damaged in a fire");
            testPackage.Bib_Info.Original_Description.Add_Note("The disc has a moderate amount of scratches, but still plays");

            testPackage.Bib_Info.Series_Part_Info.Day = "18";
            testPackage.Bib_Info.Series_Part_Info.Day_Index = 18;
            testPackage.Bib_Info.Series_Part_Info.Month = "Syyskuu";
            testPackage.Bib_Info.Series_Part_Info.Month_Index = 9;
            testPackage.Bib_Info.Series_Part_Info.Year = "1992";
            testPackage.Bib_Info.Series_Part_Info.Year_Index = 1992;

            testPackage.Bib_Info.Series_Part_Info.Enum1 = "Volume 12";
            testPackage.Bib_Info.Series_Part_Info.Enum1_Index = 12;
            testPackage.Bib_Info.Series_Part_Info.Enum2 = "Issue 3";
            testPackage.Bib_Info.Series_Part_Info.Enum2_Index = 3;
            testPackage.Bib_Info.Series_Part_Info.Enum3 = "Part 1";
            testPackage.Bib_Info.Series_Part_Info.Enum3_Index = 1;

            testPackage.Behaviors.Serial_Info.Add_Hierarchy(1, 1992, "1992");
            testPackage.Behaviors.Serial_Info.Add_Hierarchy(2, 9, "Syyskuu");
            testPackage.Behaviors.Serial_Info.Add_Hierarchy(3, 18, "18");

            testPackage.Bib_Info.SeriesTitle.Title = "Shakespeare's most famous musicals";

            testPackage.Bib_Info.Add_Target_Audience("young adults");
            testPackage.Bib_Info.Add_Target_Audience("adolescent", "marctarget");

            testPackage.Bib_Info.SobekCM_Type = TypeOfResource_SobekCM_Enum.Newspaper;

            // Add cartographic subject
            Subject_Info_Cartographics newCartographics = testPackage.Bib_Info.Add_Cartographics_Subject();
            newCartographics.Scale = "1:2000";
            newCartographics.Projection = "Conical Projection";
            newCartographics.Coordinates = "E 72°--E 148°/N 13°--N 18°";

            // Add hierarchical geographic subject
            Subject_Info_HierarchicalGeographic hierarchical = testPackage.Bib_Info.Add_Hierarchical_Geographic_Subject();
            hierarchical.Continent = "North America";
            hierarchical.Country = "United States of America";
            hierarchical.State = "Kansas";
            hierarchical.County = "Butler";
            hierarchical.City = "Augusta";

            // Add hierarchical geographic subject
            Subject_Info_HierarchicalGeographic hierarchical2 = testPackage.Bib_Info.Add_Hierarchical_Geographic_Subject();
            hierarchical2.Region = "Arctic Ocean";

            // Add hierarchical geographic subject
            Subject_Info_HierarchicalGeographic hierarchical3 = testPackage.Bib_Info.Add_Hierarchical_Geographic_Subject();
            hierarchical3.Island = "Puerto Rico";
            hierarchical3.Language = "English";
            hierarchical3.Province = "Provincial";
            hierarchical3.Territory = "Puerto Rico";
            hierarchical3.Area = "Intercontinental areas (Western Hemisphere)";

            // Add a name subject
            Subject_Info_Name subjname1 = testPackage.Bib_Info.Add_Name_Subject();
            subjname1.Authority = "lcsh";
            subjname1.Full_Name = "Garcia Lorca, Federico";
            subjname1.Dates = "1898-1936";
            subjname1.Add_Geographic("Russia");
            subjname1.Add_Geographic("Moscow");
            subjname1.Add_Genre("maps");
            subjname1.User_Submitted = true;

            // Add a title information subject
            Subject_Info_TitleInfo subjtitle1 = testPackage.Bib_Info.Add_Title_Subject();
            subjtitle1.Title_Type = Title_Type_Enum.Uniform;
            subjtitle1.Authority = "naf";
            subjtitle1.Title = "Missale Carnotense";

            // Add a standard subject
            Subject_Info_Standard subject1 = testPackage.Bib_Info.Add_Subject();
            subject1.Authority = "lcsh";
            subject1.Add_Topic("Real property");
            subject1.Add_Geographic("Mississippi");
            subject1.Add_Geographic("Tippah County");
            subject1.Add_Genre("Maps");

            // Add a standard subject
            Subject_Info_Standard subject2 = testPackage.Bib_Info.Add_Subject();
            subject2.Add_Occupation("Migrant laborers");
            subject2.Add_Genre("School district case files");

            // Add a standard subject
            Subject_Info_Standard subject3 = testPackage.Bib_Info.Add_Subject();
            subject3.Authority = "lctgm";
            subject3.Add_Topic("Educational buildings");
            subject3.Add_Geographic("Washington (D.C.)");
            subject3.Add_Temporal("1890-1910");

            // Add a standard subject
            Subject_Info_Standard subject4 = testPackage.Bib_Info.Add_Subject();
            subject4.Authority = "rvm";
            subject4.Language = "french";
            subject4.Add_Topic("Église catholique");
            subject4.Add_Topic("Histoire");
            subject4.Add_Temporal("20e siècle");

            // Add record information
            testPackage.Bib_Info.Record.Add_Catalog_Language(new Language_Info("English", "eng", "en"));
            testPackage.Bib_Info.Record.Add_Catalog_Language(new Language_Info("French", "fre", "fr"));
            testPackage.Bib_Info.Record.MARC_Creation_Date = "080303";
            testPackage.Bib_Info.Record.Add_MARC_Record_Content_Sources("FUG");
            testPackage.Bib_Info.Record.Record_Origin = "Imported from (OCLC)001213124";

            // Test the items which are in the non-MODS portion of the Bib_Info object
            testPackage.BibID = "MVS0000001";
            testPackage.VID = "00001";
            testPackage.Bib_Info.SortDate = 1234;
            testPackage.Bib_Info.SortTitle = "MAN WHO WOULD BE KING";
            testPackage.Bib_Info.Add_Temporal_Subject(1990, 2002, "Recent history");
            testPackage.Bib_Info.Add_Temporal_Subject(1990, 2002, "Lähihistoria");
            testPackage.Bib_Info.Source.Code = "UF";
            testPackage.Bib_Info.Source.Statement = "University of Florida";

            // Add an affiliation
            Affiliation_Info affiliation1 = new Affiliation_Info();
            affiliation1.University = "University of Florida";
            affiliation1.Campus = "Gainesville Campus";
            affiliation1.College = "College of Engineering";
            affiliation1.Department = "Computer Engineering Department";
            affiliation1.Unit = "Robotics";
            affiliation1.Name_Reference = "NAM4";
            testPackage.Bib_Info.Add_Affiliation(affiliation1);

            // Add a related item
            Related_Item_Info relatedItem1 = new Related_Item_Info();
            relatedItem1.SobekCM_ID = "UF00001234";
            relatedItem1.Relationship = Related_Item_Type_Enum.Preceding;
            relatedItem1.Publisher = "Gainesville Sun Publishing House";
            relatedItem1.Add_Note(new Note_Info("Digitized with funding from NEH", Note_Type_Enum.Funding));
            relatedItem1.Add_Note(new Note_Info("Gainesville Bee was the precursor to this item"));
            relatedItem1.Main_Title.NonSort = "The";
            relatedItem1.Main_Title.Title = "Gainesville Bee";
            relatedItem1.Add_Identifier("01234353", "oclc");
            relatedItem1.Add_Identifier("002232311", "aleph");
            Name_Info ri_name = new Name_Info();
            ri_name.Full_Name = "Hills, Bryan";
            ri_name.Terms_Of_Address = "Mr.";
            ri_name.Name_Type = Name_Info_Type_Enum.Personal;
            ri_name.Add_Role("author");
            relatedItem1.Add_Name(ri_name);
            relatedItem1.URL = @"http://www.uflib.ufl.edu/ufdc/?b=UF00001234";
            relatedItem1.URL_Display_Label = "Full Text";
            testPackage.Bib_Info.Add_Related_Item(relatedItem1);

            // Add another related item
            Related_Item_Info relatedItem2 = new Related_Item_Info();
            relatedItem2.Relationship = Related_Item_Type_Enum.Succeeding;
            relatedItem2.SobekCM_ID = "UF00009999";
            relatedItem2.Main_Title.NonSort = "The";
            relatedItem2.Main_Title.Title = "Daily Sun";
            relatedItem2.Add_Identifier("0125437", "oclc");
            relatedItem2.Add_Note("Name change occured in Fall 1933");
            relatedItem2.Start_Date = "Fall 1933";
            relatedItem2.End_Date = "December 31, 1945";
            testPackage.Bib_Info.Add_Related_Item(relatedItem2);

            // Add some processing parameters
            testPackage.Behaviors.Add_Aggregation("JUV");
            testPackage.Behaviors.Add_Aggregation("DLOC");
            testPackage.Behaviors.Add_Aggregation("DLOSA1");
            testPackage.Behaviors.Add_Aggregation("ALICE");
            testPackage.Behaviors.Add_Aggregation("ARTE");

            testPackage.Web.GUID = "GUID!";
            testPackage.Behaviors.Add_Wordmark("DLOC");
            testPackage.Behaviors.Add_Wordmark("UFSPEC");
            testPackage.Behaviors.Main_Thumbnail = "00001thm.jpg";

            // Add some downloads
            testPackage.Divisions.Download_Tree.Add_File("MVS_Complete.PDF");
            testPackage.Divisions.Download_Tree.Add_File("MVS_Complete.MP2");
            testPackage.Divisions.Download_Tree.Add_File("MVS_Part1.MP2");
            testPackage.Divisions.Download_Tree.Add_File("MVS_Part1.PDF");

            // Add some coordinate information
            GeoSpatial_Information geoSpatial = new GeoSpatial_Information();
            testPackage.Add_Metadata_Module(GlobalVar.GEOSPATIAL_METADATA_MODULE_KEY, geoSpatial);
            geoSpatial.Add_Point(29.530151, -82.301459, "Lake Wauberg");
            geoSpatial.Add_Point(29.634352, -82.350640, "Veterinary School");
            Coordinate_Polygon polygon = new Coordinate_Polygon();
            polygon.Label = "University of Florida Campus";
            polygon.Add_Edge_Point(new Coordinate_Point(29.651435, -82.339869, String.Empty));
            polygon.Add_Edge_Point(new Coordinate_Point(29.641216, -82.340298, String.Empty));
            polygon.Add_Edge_Point(new Coordinate_Point(29.629503, -82.371969, String.Empty));
            polygon.Add_Edge_Point(new Coordinate_Point(29.649645, -82.371712, String.Empty));
            polygon.Add_Inner_Point(29.649794, -82.351971, "Stadium");
            polygon.Add_Inner_Point(29.650988, -82.341156, "Library");
            geoSpatial.Add_Polygon(polygon);
            Coordinate_Line line = new Coordinate_Line();
            line.Label = "Waldo Road";
            line.Add_Point(29.652852, -82.310944, "Gainesville");
            line.Add_Point(29.716681, -82.268372, String.Empty);
            line.Add_Point(29.791494, -82.167778, "Waldo");
            geoSpatial.Add_Line(line);

            // Add some performing arts information
            Performing_Arts_Info partInfo = new Performing_Arts_Info();
            testPackage.Add_Metadata_Module("PerformingArts", partInfo);
            partInfo.Performance = "Hamlet";
            partInfo.Performance_Date = "August 12, 1923";
            Performer performer1 = partInfo.Add_Performer("Sullivan, Mark");
            performer1.Sex = "M";
            performer1.LifeSpan = "1873-";
            performer1.Occupation = "actor";
            performer1.Title = "Mr.";

            Performer performer2 = partInfo.Add_Performer("Waldbart, Julia");
            performer2.Sex = "F";
            performer2.LifeSpan = "1876-";
            performer2.Occupation = "actress";
            performer2.Title = "Mrs.";

            // Add some oral history information
            Oral_Interview_Info oralInfo = new Oral_Interview_Info();
            testPackage.Add_Metadata_Module(  "OralInterview", oralInfo);
            oralInfo.Interviewee = "Edwards, Herm";
            oralInfo.Interviewer = "Proctor, Samual";

            // Add some learning object resource information
            LearningObjectMetadata lomInfo = new LearningObjectMetadata();
            testPackage.Add_Metadata_Module( GlobalVar.IEEE_LOM_METADATA_MODULE_KEY, lomInfo );
            lomInfo.AggregationLevel = AggregationLevelEnum.level3;
            lomInfo.Status = StatusEnum.draft;
            LOM_System_Requirements lomReq1 = new LOM_System_Requirements();
            lomReq1.RequirementType = RequirementTypeEnum.operating_system;
            lomReq1.Name.Value = "Windows";
            lomReq1.MinimumVersion = "Windows XP";
            lomReq1.MaximumVersion = "Windows 7";
            lomInfo.Add_SystemRequirements(lomReq1);
            LOM_System_Requirements lomReq2 = new LOM_System_Requirements();
            lomReq2.RequirementType = RequirementTypeEnum.software;
            lomReq2.Name.Value = "Java SDK";
            lomReq2.MinimumVersion = "1.7.1";
            lomReq2.MaximumVersion = "2.09";
            lomInfo.Add_SystemRequirements(lomReq2);
            lomInfo.InteractivityType = InteractivityTypeEnum.mixed;
            lomInfo.Add_LearningResourceType("exercise");
            lomInfo.Add_LearningResourceType("Tutorials", "encdlwebpedagogicaltype");
            lomInfo.InteractivityLevel = InteractivityLevelEnum.high;
            lomInfo.Add_IntendedEndUserRole(IntendedEndUserRoleEnum.learner);
            lomInfo.Add_Context("Undergraduate lower division", "enclearningcontext");
            lomInfo.Add_Context("15", "grade");
            lomInfo.Add_Context("16", "grade");
            lomInfo.Add_Context("5", "group");
            lomInfo.Add_TypicalAgeRange("suitable for children over 7", "en");
            lomInfo.Add_TypicalAgeRange("2-8");
            lomInfo.DifficultyLevel = DifficultyLevelEnum.medium;
            lomInfo.TypicalLearningTime = "PT45M";

            LOM_Classification lomClassification1 = new LOM_Classification();
            lomInfo.Add_Classification(lomClassification1);
            lomClassification1.Purpose.Value = "Discipline";
            LOM_TaxonPath lomTaxonPath1 = new LOM_TaxonPath();
            lomClassification1.Add_TaxonPath(lomTaxonPath1);
            lomTaxonPath1.Add_SourceName("ARIADNE");
            LOM_Taxon lomTaxon1 = new LOM_Taxon();
            lomTaxonPath1.Add_Taxon(lomTaxon1);
            lomTaxon1.ID = "BF120";
            lomTaxon1.Add_Entry("Work_History", "en");
            lomTaxon1.Add_Entry("Historie", "nl");
            LOM_Taxon lomTaxon2 = new LOM_Taxon();
            lomTaxonPath1.Add_Taxon(lomTaxon2);
            lomTaxon2.ID = "BF120.1";
            lomTaxon2.Add_Entry("American Work_History", "en");
            LOM_Taxon lomTaxon3 = new LOM_Taxon();
            lomTaxonPath1.Add_Taxon(lomTaxon3);
            lomTaxon3.ID = "BF120.1.4";
            lomTaxon3.Add_Entry("American Civil War", "en");

            LOM_Classification lomClassification2 = new LOM_Classification();
            lomInfo.Add_Classification(lomClassification2);
            lomClassification2.Purpose.Value = "Educational Objective";

            LOM_TaxonPath lomTaxonPath2 = new LOM_TaxonPath();
            lomClassification2.Add_TaxonPath(lomTaxonPath2);
            lomTaxonPath2.Add_SourceName("Common Core Standards", "en");
            LOM_Taxon lomTaxon4 = new LOM_Taxon();
            lomTaxonPath2.Add_Taxon(lomTaxon4);
            lomTaxon4.ID = "CCS.Math.Content";
            LOM_Taxon lomTaxon5 = new LOM_Taxon();
            lomTaxonPath2.Add_Taxon(lomTaxon5);
            lomTaxon5.ID = "3";
            lomTaxon5.Add_Entry("Grade 3", "en");
            LOM_Taxon lomTaxon6 = new LOM_Taxon();
            lomTaxonPath2.Add_Taxon(lomTaxon6);
            lomTaxon6.ID = "OA";
            lomTaxon6.Add_Entry("Operations and Algebraic Thinking", "en");
            LOM_Taxon lomTaxon7 = new LOM_Taxon();
            lomTaxonPath2.Add_Taxon(lomTaxon7);
            lomTaxon7.ID = "A";
            lomTaxon7.Add_Entry("Represent and solve problems involving multiplication and division.", "en");
            LOM_Taxon lomTaxon8 = new LOM_Taxon();
            lomTaxonPath2.Add_Taxon(lomTaxon8);
            lomTaxon8.ID = "3";
            lomTaxon8.Add_Entry("Use multiplication and division within 100 to solve word problems in situations involving equal groups, arrays, and measurement quantities, e.g., by using drawings and equations with a symbol for the unknown number to represent the problem.", "en");

            LOM_TaxonPath lomTaxonPath3 = new LOM_TaxonPath();
            lomClassification2.Add_TaxonPath(lomTaxonPath3);
            lomTaxonPath3.Add_SourceName("Common Core Standards", "en");
            LOM_Taxon lomTaxon14 = new LOM_Taxon();
            lomTaxonPath3.Add_Taxon(lomTaxon14);
            lomTaxon14.ID = "CCS.Math.Content";
            LOM_Taxon lomTaxon15 = new LOM_Taxon();
            lomTaxonPath3.Add_Taxon(lomTaxon15);
            lomTaxon15.ID = "3";
            lomTaxon15.Add_Entry("Grade 3", "en");
            LOM_Taxon lomTaxon16 = new LOM_Taxon();
            lomTaxonPath3.Add_Taxon(lomTaxon16);
            lomTaxon16.ID = "OA";
            lomTaxon16.Add_Entry("Operations and Algebraic Thinking", "en");
            LOM_Taxon lomTaxon17 = new LOM_Taxon();
            lomTaxonPath3.Add_Taxon(lomTaxon17);
            lomTaxon17.ID = "A";
            lomTaxon17.Add_Entry("Represent and solve problems involving multiplication and division.", "en");
            LOM_Taxon lomTaxon18 = new LOM_Taxon();
            lomTaxonPath3.Add_Taxon(lomTaxon18);
            lomTaxon18.ID = "4";
            lomTaxon18.Add_Entry("Determine the unknown whole number in a multiplication or division equation relating three whole numbers. For example, determine the unknown number that makes the equation true in each of the equations 8 × ? = 48, 5 = _ ÷ 3, 6 × 6 = ?", "en");

            // Add some views and interfaces
            testPackage.Behaviors.Clear_Web_Skins();
            testPackage.Behaviors.Add_Web_Skin("dLOC");
            testPackage.Behaviors.Add_Web_Skin("UFDC");
            testPackage.Behaviors.Add_View(View_Enum.JPEG2000);
            testPackage.Behaviors.Add_View(View_Enum.JPEG);
            testPackage.Behaviors.Add_View(View_Enum.RELATED_IMAGES);
            testPackage.Behaviors.Add_View(View_Enum.HTML, "Full Document", "MVS001214.html");

            // Create the chapters and pages and link them
            Division_TreeNode chapter1 = new Division_TreeNode("Chapter", "First Chapter");
            Page_TreeNode page1 = new Page_TreeNode("First Page");
            Page_TreeNode page2 = new Page_TreeNode("Page 2");
            chapter1.Nodes.Add(page1);
            chapter1.Nodes.Add(page2);
            Division_TreeNode chapter2 = new Division_TreeNode("Chapter", "Last Chapter");
            Page_TreeNode page3 = new Page_TreeNode("Page 3");
            Page_TreeNode page4 = new Page_TreeNode("Last Page");
            chapter2.Nodes.Add(page3);
            chapter2.Nodes.Add(page4);
            testPackage.Divisions.Physical_Tree.Roots.Add(chapter1);
            testPackage.Divisions.Physical_Tree.Roots.Add(chapter2);

            // Create the files
            SobekCM_File_Info file1_1 = new SobekCM_File_Info("2000626_0001.jp2", 2120, 1100);
            SobekCM_File_Info file1_2 = new SobekCM_File_Info("2000626_0001.jpg", 630, 330);
            SobekCM_File_Info file1_3 = new SobekCM_File_Info("2000626_0001.tif");
            SobekCM_File_Info file2_1 = new SobekCM_File_Info("2000626_0002.jp2", 1754, 2453);
            SobekCM_File_Info file2_2 = new SobekCM_File_Info("2000626_0002.jpg", 630, 832);
            SobekCM_File_Info file2_3 = new SobekCM_File_Info("2000626_0002.tif");
            SobekCM_File_Info file3_1 = new SobekCM_File_Info("2000626_0003.jp2", 2321, 1232);
            SobekCM_File_Info file3_2 = new SobekCM_File_Info("2000626_0003.jpg", 630, 342);
            SobekCM_File_Info file3_3 = new SobekCM_File_Info("2000626_0003.tif");
            SobekCM_File_Info file4_1 = new SobekCM_File_Info("2000626_0004.jp2", 2145, 1024);
            SobekCM_File_Info file4_2 = new SobekCM_File_Info("2000626_0004.jpg", 630, 326);
            SobekCM_File_Info file4_3 = new SobekCM_File_Info("2000626_0004.tif");

            // Link the files to the pages
            page1.Files.Add(file1_1);
            page1.Files.Add(file1_2);
            page1.Files.Add(file1_3);
            page2.Files.Add(file2_1);
            page2.Files.Add(file2_2);
            page2.Files.Add(file2_3);
            page3.Files.Add(file3_1);
            page3.Files.Add(file3_2);
            page3.Files.Add(file3_3);
            page4.Files.Add(file4_1);
            page4.Files.Add(file4_2);
            page4.Files.Add(file4_3);

            // Add the DAITSS information
            DAITSS_Info daitssInfo = new DAITSS_Info();
            daitssInfo.Account = "FTU";
            daitssInfo.SubAccount = "CLAS";
            daitssInfo.Project = "UFDC";
            daitssInfo.toArchive = true;
            testPackage.Add_Metadata_Module(GlobalVar.DAITSS_METADATA_MODULE_KEY, daitssInfo);

            // Save this package
            testPackage.Source_Directory = directory;
            return testPackage;
        }
        private bool get_attributes_from_jpeg2000(SobekCM_File_Info JPEG2000_File, string File)
        {
            try
            {
                // Get the height and width of this JPEG file
                FileStream reader = new FileStream(File, FileMode.Open, FileAccess.Read);
                int[] previousValues = { 0, 0, 0, 0 };
                int bytevalue = reader.ReadByte();
                int count = 1;
                while (bytevalue != -1)
                {
                    // Move this value into the array
                    previousValues[0] = previousValues[1];
                    previousValues[1] = previousValues[2];
                    previousValues[2] = previousValues[3];
                    previousValues[3] = bytevalue;

                    // Is this IHDR?
                    if ((previousValues[0] == 105) && (previousValues[1] == 104) &&
                        (previousValues[2] == 100) && (previousValues[3] == 114))
                    {
                        break;
                    }

                    // Is this the first four bytes and does it match the output from Kakadu 3-2?
                    if ((count == 4) && (previousValues[0] == 255) && (previousValues[1] == 79) &&
                        (previousValues[2] == 255) && (previousValues[3] == 81))
                    {
                        reader.ReadByte();
                        reader.ReadByte();
                        reader.ReadByte();
                        reader.ReadByte();
                        break;
                    }

                    // Read the next byte
                    bytevalue = reader.ReadByte();
                    count++;
                }

                // Now, read ahead for the height and width
                JPEG2000_File.Height = (ushort)((((((reader.ReadByte() * 256) + reader.ReadByte()) * 256) + reader.ReadByte()) * 256) + reader.ReadByte());
                JPEG2000_File.Width = (ushort)((((((reader.ReadByte() * 256) + reader.ReadByte()) * 256) + reader.ReadByte()) * 256) + reader.ReadByte());
                reader.Close();

                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary> Reads the amdSec at the current position in the XmlTextReader and associates it with the 
        /// entire package  </summary>
        /// <param name="Input_XmlReader"> Open XmlReader from which to read the metadata </param>
        /// <param name="Return_Package"> Package into which to read the metadata</param>
        /// <param name="Options"> Dictionary of any options which this METS section reader may utilize</param>
        /// <returns> TRUE if successful, otherwise FALSE</returns>
        /// <remarks> One option is REQUIRED for this to work, you must pass in  a Dictionary&lt;string,SobekCM_File_Info&gt;
        /// generic dictionary with all the pre-collection file information stored by fileid.  It should be include in the 
        /// Options dictionary under the key 'SobekCM_FileInfo_METS_amdSec_ReaderWriter:Files_By_FileID'.</remarks>
        public bool Read_amdSec(XmlReader Input_XmlReader, SobekCM_Item Return_Package, Dictionary<string, object> Options)
        {
            Dictionary<string, SobekCM_File_Info> files_by_fileid = null;
            if ((Options == null) || (!Options.ContainsKey("SobekCM_FileInfo_METS_amdSec_ReaderWriter:Files_By_FileID")))
                return false;

            files_by_fileid = (Dictionary<string, SobekCM_File_Info>) Options["SobekCM_FileInfo_METS_amdSec_ReaderWriter:Files_By_FileID"];

            string fileid = String.Empty;

            // Loop through reading each XML node
            do
            {
                // If this is the end of this section, return
                if ((Input_XmlReader.NodeType == XmlNodeType.EndElement) && (Input_XmlReader.Name == sobekcm_namespace + ":FileInfo"))
                    return true;

                // get the right division information based on node type
                switch (Input_XmlReader.NodeType)
                {
                    case XmlNodeType.EndElement:
                        if (Input_XmlReader.Name == sobekcm_namespace + ":FileInfo")
                            return true;
                        break;

                    case XmlNodeType.Element:
                        if ((Input_XmlReader.Name == sobekcm_namespace + ":File") && (Input_XmlReader.HasAttributes) && (Input_XmlReader.MoveToAttribute("fileid")))
                        {
                            fileid = Input_XmlReader.Value;

                            // Save this information
                            SobekCM_File_Info existingFile = null;
                            if (!files_by_fileid.ContainsKey(fileid))
                            {
                                existingFile = new SobekCM_File_Info(String.Empty);
                                files_by_fileid[fileid] = existingFile;
                            }
                            else
                            {
                                existingFile = files_by_fileid[fileid];
                            }

                            try
                            {
                                if (Input_XmlReader.MoveToAttribute("width"))
                                    existingFile.Width = Convert.ToUInt16(Input_XmlReader.Value);

                                if (Input_XmlReader.MoveToAttribute("height"))
                                    existingFile.Height = Convert.ToUInt16(Input_XmlReader.Value);
                            }
                            catch
                            {
                            }
                        }
                        break;
                }
            } while (Input_XmlReader.Read());

            // Return false since this read all the way to the end of the steam
            return false;
        }
        private bool complete_item_submission(SobekCM_Item Item_To_Complete, Custom_Tracer Tracer )
        {
            // Set an initial flag
            criticalErrorEncountered = false;

            string[] all_files = Directory.GetFiles(digitalResourceDirectory);
            SortedList<string, List<string>> image_files = new SortedList<string, List<string>>();
            SortedList<string, List<string>> download_files = new SortedList<string, List<string>>();
            foreach (string thisFile in all_files)
            {
                FileInfo thisFileInfo = new FileInfo(thisFile);

                if ((thisFileInfo.Name.IndexOf("agreement.txt") != 0) && (thisFileInfo.Name.IndexOf("TEMP000001_00001.mets") != 0) && (thisFileInfo.Name.IndexOf("doc.xml") != 0) && (thisFileInfo.Name.IndexOf("ufdc_mets.xml") != 0) && (thisFileInfo.Name.IndexOf("marc.xml") != 0))
                {
                    // Get information about this files name and extension
                    string extension_upper = thisFileInfo.Extension.ToUpper();
                    string filename_sans_extension = thisFileInfo.Name.Replace(thisFileInfo.Extension, "");
                    string name_upper = thisFileInfo.Name.ToUpper();

                    // Is this a page image?
                    if ((extension_upper == ".JPG") || (extension_upper == ".TIF") || (extension_upper == ".JP2") || (extension_upper == ".JPX"))
                    {
                        // Exclude .QC.jpg files
                        if (name_upper.IndexOf(".QC.JPG") < 0)
                        {
                            // If this is a thumbnail, trim off the THM part on the file name
                            if (name_upper.IndexOf("THM.JPG") > 0)
                            {
                                filename_sans_extension = filename_sans_extension.Substring(0, filename_sans_extension.Length - 3);
                            }

                            // Is this the first image file with this name?
                            if (image_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                image_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List<string> newImageGrouping = new List<string> {thisFileInfo.Name};
                                image_files[filename_sans_extension.ToLower()] = newImageGrouping;
                            }
                        }
                    }
                    else
                    {
                        // If this does not match the exclusion regular expression, than add this
                        if ((!Regex.Match(thisFileInfo.Name, SobekCM_Library_Settings.Files_To_Exclude_From_Downloads, RegexOptions.IgnoreCase).Success) && ( String.Compare(thisFileInfo.Name, Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html", true ) != 0 ))
                        {
                            // Is this the first image file with this name?
                            if (download_files.ContainsKey(filename_sans_extension.ToLower()))
                            {
                                download_files[filename_sans_extension.ToLower()].Add(thisFileInfo.Name);
                            }
                            else
                            {
                                List<string> newDownloadGrouping = new List<string> {thisFileInfo.Name};
                                download_files[filename_sans_extension.ToLower()] = newDownloadGrouping;
                            }
                        }
                    }
                }
            }

            // This package is good to go, so build it, save, etc...
            try
            {
                // Save the METS file to the database and back to the directory
                Item_To_Complete.Source_Directory = digitalResourceDirectory;

                // Step through and add each file
                Item_To_Complete.Divisions.Download_Tree.Clear();

                // Step through each file
                bool error_reading_file_occurred = false;

                // Add the image files first
                bool jpeg_added = false;
                bool jp2_added = false;
                foreach (string thisFileKey in image_files.Keys)
                {
                    // Get the list of files
                    List<string> theseFiles = image_files[thisFileKey];

                    // Add each file
                    foreach (string thisFile in theseFiles)
                    {
                        // Create the new file object and compute a label
                        System.IO.FileInfo fileInfo = new System.IO.FileInfo(thisFile);
                        SobekCM.Resource_Object.Divisions.SobekCM_File_Info newFile = new SobekCM.Resource_Object.Divisions.SobekCM_File_Info(fileInfo.Name);
                        string label = fileInfo.Name.Replace(fileInfo.Extension, "");
                        if (System.Web.HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey] != null)
                        {
                            string possible_label = System.Web.HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey].ToString();
                            if (possible_label.Length > 0)
                                label = possible_label;
                        }

                        // Add this file
                        item.Divisions.Physical_Tree.Add_File(newFile, label);

                        // Seperate code for JP2 and JPEG type files
                        string extension = fileInfo.Extension.ToUpper();
                        if (extension.IndexOf("JP2") >= 0)
                        {
                            if (!error_reading_file_occurred)
                            {
                                if (!newFile.Compute_Jpeg2000_Attributes(item.Source_Directory))
                                    error_reading_file_occurred = true;
                            }
                            jp2_added = true;
                        }
                        else
                        {
                            if (!error_reading_file_occurred)
                            {
                                if (!newFile.Compute_Jpeg_Attributes(item.Source_Directory))
                                    error_reading_file_occurred = true;
                            }
                            jpeg_added = true;
                        }
                    }
                }

                // Add the download files next
                foreach(string thisFileKey in download_files.Keys )
                {
                    // Get the list of files
                    List<string> theseFiles = download_files[thisFileKey];

                    // Add each file
                    foreach (string thisFile in theseFiles)
                    {
                        // Create the new file object and compute a label
                        FileInfo fileInfo = new FileInfo(thisFile);
                        SobekCM_File_Info newFile = new SobekCM_File_Info(fileInfo.Name);
                        string label = fileInfo.Name.Replace( fileInfo.Extension, "");
                        if (HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey] != null)
                        {
                            string possible_label = HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + thisFileKey].ToString();
                            if (possible_label.Length > 0)
                                label = possible_label;
                        }

                        // Add this file
                        Item_To_Complete.Divisions.Download_Tree.Add_File(newFile, label);
                    }
                }

                // Add the JPEG2000 and JPEG-specific viewers
                item.Behaviors.Clear_Views();
                if (jpeg_added)
                {
                    item.Behaviors.Add_View(SobekCM.Resource_Object.Behaviors.View_Enum.JPEG);
                }
                if (jp2_added)
                {
                    item.Behaviors.Add_View(SobekCM.Resource_Object.Behaviors.View_Enum.JPEG2000);
                }

                // Determine the total size of the package before saving
                string[] all_files_final = Directory.GetFiles(digitalResourceDirectory);
                double size = all_files_final.Aggregate<string, double>(0, (current, thisFile) => current + (((new FileInfo(thisFile)).Length)/1024));
                Item_To_Complete.DiskSize_MB = size;

                // Save to the database
                try
                {
                    SobekCM_Database.Save_Digital_Resource( Item_To_Complete );
                    SobekCM_Database.Save_Behaviors(Item_To_Complete, Item_To_Complete.Behaviors.Text_Searchable, false);
                }
                catch (Exception ee)
                {
                    StreamWriter writer = new StreamWriter(digitalResourceDirectory + "\\exception.txt", false);
                    writer.WriteLine( "ERROR CAUGHT WHILE SAVING DIGITAL RESOURCE");
                    writer.WriteLine( DateTime.Now.ToString());
                    writer.WriteLine();
                    writer.WriteLine( ee.Message );
                    writer.WriteLine( ee.StackTrace );
                    writer.Flush();
                    writer.Close();
                    throw;
                }

                // Assign the file root and assoc file path
                Item_To_Complete.Web.File_Root = Item_To_Complete.BibID.Substring(0, 2) + "\\" + Item_To_Complete.BibID.Substring(2, 2) + "\\" + Item_To_Complete.BibID.Substring(4, 2) + "\\" + Item_To_Complete.BibID.Substring(6, 2) + "\\" + Item_To_Complete.BibID.Substring(8, 2);
                Item_To_Complete.Web.AssocFilePath = Item_To_Complete.Web.File_Root + "\\" + Item_To_Complete.VID + "\\";

                // Create the static html pages
                string base_url = currentMode.Base_URL;
                try
                {
                    Static_Pages_Builder staticBuilder = new Static_Pages_Builder(SobekCM_Library_Settings.System_Base_URL, SobekCM_Library_Settings.Base_Data_Directory, Translator, codeManager, itemList, iconList, webSkin);
                    string filename = digitalResourceDirectory + "\\" + Item_To_Complete.BibID + "_" + Item_To_Complete.VID + ".html";
                    staticBuilder.Create_Item_Citation_HTML(Item_To_Complete, filename, String.Empty);
                }
                catch (Exception ee)
                {
                    string error = ee.Message;
                }

                currentMode.Base_URL = base_url;

                // Save the rest of the metadata
                Item_To_Complete.Save_SobekCM_METS();

                // Finally, set the item for more processing if there were any files
                if (((image_files.Count > 0) || (download_files.Count > 0)) && ( Item_To_Complete.Web.ItemID > 0 ))
                {
                    Database.SobekCM_Database.Update_Additional_Work_Needed_Flag(Item_To_Complete.Web.ItemID, true, Tracer);
                }
            }
            catch (Exception ee)
            {
                validationErrors.Add("Error encountered during item save!");
                validationErrors.Add(ee.ToString().Replace("\r", "<br />"));

                // Set an initial flag
                criticalErrorEncountered = true;

                string error_body = "<strong>ERROR ENCOUNTERED DURING ONLINE FILE MANAGEMENT</strong><br /><br /><blockquote>Title: " + Item_To_Complete.Bib_Info.Main_Title.Title + "<br />Permanent Link: <a href=\"" + base.currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "\">" + base.currentMode.Base_URL + "/" + Item_To_Complete.BibID + "/" + Item_To_Complete.VID + "</a><br />User: "******"<br /><br /></blockquote>" + ee.ToString().Replace("\n", "<br />");
                string error_subject = "Error during file management for '" + Item_To_Complete.Bib_Info.Main_Title.Title + "'";
                string email_to = SobekCM_Library_Settings.System_Error_Email;
                if (email_to.Length == 0)
                    email_to = SobekCM_Library_Settings.System_Email;
                Database.SobekCM_Database.Send_Database_Email(email_to, error_subject, error_body, true, false, -1);
            }

            return criticalErrorEncountered;
        }