/// <summary> Recalculates all the checksums for associated files </summary> /// <param name="Recalculate_All"> Flag indicates whether to recalculate all files, regardless of need </param> /// <param name="Progress_Delegate"> Progress delegate is called to update any progress displays </param> public void Calculate_Checksum(bool Recalculate_All, New_SobekCM_Bib_Package_Progress_Task_Group Progress_Delegate) { // Get the list of all pages from this division trees List<abstract_TreeNode> pageNodes = physicalDivisionTree.Pages_PreOrder; List<abstract_TreeNode> fileNodes = downloadDivisionTree.Pages_PreOrder; // Update progress if (Progress_Delegate != null) { Progress_Delegate("Calculating checksums", "Checking all files", 0, 2); } // Count how many pages to calculate for int total_files = 0; foreach (Page_TreeNode pageNode in pageNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0))) { total_files++; } } } foreach (Page_TreeNode pageNode in fileNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0))) { total_files++; } } } if (total_files == 0) return; // Now caulcate int file_count = 0; FileMD5 checksummer = new FileMD5(); foreach (Page_TreeNode pageNode in pageNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((thisFile.METS_LocType == SobekCM_File_Info_Type_Enum.SYSTEM) && ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0)))) { // Perform in a try catch try { // Get the size first FileInfo thisFileInfo = new FileInfo(source_directory + "/" + thisFile.System_Name); thisFile.Size = thisFileInfo.Length; // Get the checksum, if it doesn't exist if ((String.IsNullOrEmpty(thisFile.Checksum)) || (Recalculate_All)) { thisFile.Checksum = checksummer.Calculate_Checksum(source_directory + "/" + thisFile.System_Name); thisFile.Checksum_Type = "MD5"; } } catch {} file_count++; // Update progress if (Progress_Delegate != null) { Progress_Delegate("Calculating checksums", "Calculating '" + thisFile.System_Name + "'", file_count, total_files); } } } } foreach (Page_TreeNode pageNode in fileNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((thisFile.METS_LocType == SobekCM_File_Info_Type_Enum.SYSTEM) && ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0)))) { // Perform in a try catch try { // Get the size first FileInfo thisFileInfo = new FileInfo(source_directory + "/" + thisFile.System_Name); thisFile.Size = thisFileInfo.Length; // Get the checksum, if it doesn't exist if ((String.IsNullOrEmpty(thisFile.Checksum)) || (Recalculate_All)) { thisFile.Checksum = checksummer.Calculate_Checksum(source_directory + "/" + thisFile.System_Name); thisFile.Checksum_Type = "MD5"; } } catch{} file_count++; // Update progress if (Progress_Delegate != null) { Progress_Delegate("Calculating checksums", "Calculating '" + thisFile.System_Name + "'", file_count, total_files); } } } } // Update progress if (Progress_Delegate != null) { Progress_Delegate("Checksum Complete", "Checksum Complete", file_count, total_files); } }
/// <summary> Writes the formatted metadata from the provided item to a TextWriter (usually to an output stream) </summary> /// <param name="Output_Stream"></param> /// <param name="Item_To_Save"> Package with all the metadata to save </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 write </param> /// <returns>TRUE if successful, otherwise FALSE </returns> /// <remarks> OPTIONS: Accepts 'METS_File_ReaderWriter:METS_Writing_Profile', otherwise the default METS /// writing profile is utilized. </remarks> public bool Write_Metadata(TextWriter Output_Stream, SobekCM_Item Item_To_Save, Dictionary<string, object> Options, out string Error_Message) { // PERHAPS MAKE THESE OPTIONS? List<string> mimes_to_exclude = new List<string>(); const bool MINIMIZE_FILE_SIZE = false; // Get the METS writing profile METS_Writing_Profile profile = ResourceObjectSettings.MetadataConfig.Default_METS_Writing_Profile; // Set default error outpt message Error_Message = String.Empty; // Ensure the METS ID is set from BibID and VID if (Item_To_Save.METS_Header.ObjectID.Length == 0) { Item_To_Save.METS_Header.ObjectID = Item_To_Save.BibID + "_" + Item_To_Save.VID; if (Item_To_Save.VID.Length == 0) Item_To_Save.METS_Header.ObjectID = Item_To_Save.BibID; } // If this is bib level, it is different if ((Item_To_Save.VID == "*****") || (Item_To_Save.METS_Header.RecordStatus_Enum == METS_Record_Status.BIB_LEVEL)) Item_To_Save.METS_Header.ObjectID = Item_To_Save.BibID; // If this is juat a project XML, do this differently if (Item_To_Save.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.Project) { Item_To_Save.Bib_Info.Main_Title.Title = "Project level metadata for '" + Item_To_Save.BibID + "'"; Item_To_Save.METS_Header.ObjectID = Item_To_Save.BibID; } // Ensure the source code appears in the METS header correctly Item_To_Save.METS_Header.Creator_Organization = Item_To_Save.Bib_Info.Source.Code; if ((Item_To_Save.Bib_Info.Source.Statement.Length > 0) && (String.Compare(Item_To_Save.Bib_Info.Source.Statement, Item_To_Save.Bib_Info.Source.Code, StringComparison.OrdinalIgnoreCase) != 0)) { Item_To_Save.METS_Header.Creator_Organization = Item_To_Save.Bib_Info.Source.Code + "," + Item_To_Save.Bib_Info.Source.XML_Safe_Statement; } // Get the list of divisions from the physical tree and the download/other file tre List<abstract_TreeNode> physicalDivisions = Item_To_Save.Divisions.Physical_Tree.Divisions_PreOrder; List<abstract_TreeNode> downloadDivisions = Item_To_Save.Divisions.Download_Tree.Divisions_PreOrder; List<abstract_TreeNode> allDivisions = new List<abstract_TreeNode>(); List<SobekCM_File_Info> allFiles = new List<SobekCM_File_Info>(); #region Prepare the list of divisions and files to be written by assigning proper ID's and groupid's to all // Create some private variables for this int page_and_group_number = 1; int division_number = 1; bool hasPageFiles = false; bool hasDownloadFiles = false; Dictionary<string, List<SobekCM_File_Info>> mimeHash = new Dictionary<string, List<SobekCM_File_Info>>(); List<string> fileids_used = new List<string>(); // Clear any existing ID's here since the ID's are only used for writing METS files foreach (abstract_TreeNode thisNode in physicalDivisions) { thisNode.ID = String.Empty; thisNode.DMDID = String.Empty; thisNode.ADMID = String.Empty; } // First, assign group numbers for all the files on each page (physical or other) // Group numbers in the METS file correspond to files on the same page (physical or other) // At the same time, we will build the list of all files and files by mime type foreach (abstract_TreeNode thisNode in physicalDivisions) { // If this node was already hit (perhaps if a div has two parent divs), // then skip it if (thisNode.ID.Length > 0) continue; // Add this to the list of all nodes allDivisions.Add(thisNode); // Was this a PAGE or a DIVISION node? if (thisNode.Page) { // Get this page node Page_TreeNode pageNode = (Page_TreeNode) thisNode; // Only do anything if there are actually any files here if ((pageNode.Files != null) && (pageNode.Files.Count > 0)) { // Set the page ID here pageNode.ID = "PAGE" + page_and_group_number; // Step through any files under this page foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Set the ADMID and DMDID to empty in preparation for METS writing thisFile.ADMID = String.Empty; thisFile.DMDID = String.Empty; // If no file name, skip this if (String.IsNullOrEmpty(thisFile.System_Name)) continue; // Get this file extension and MIME type string fileExtension = thisFile.File_Extension; string mimetype = thisFile.MIME_Type(thisFile.File_Extension); // If this is going to be excluded from appearing in the METS file, just skip // it here as well. if (!mimes_to_exclude.Contains(mimetype)) { // Set the group number on this file thisFile.Group_Number = "G" + page_and_group_number; // Set the ID for this file as well switch (mimetype) { case "image/tiff": thisFile.ID = "TIF" + page_and_group_number; break; case "text/plain": thisFile.ID = "TXT" + page_and_group_number; break; case "image/jpeg": if (thisFile.System_Name.ToLower().IndexOf("thm.jp") > 0) { thisFile.ID = "THUMB" + page_and_group_number; mimetype = mimetype + "-thumbnails"; } else thisFile.ID = "JPEG" + page_and_group_number; break; case "image/gif": if (thisFile.System_Name.ToLower().IndexOf("thm.gif") > 0) { thisFile.ID = "THUMB" + page_and_group_number; mimetype = mimetype + "-thumbnails"; } else thisFile.ID = "GIF" + page_and_group_number; break; case "image/jp2": thisFile.ID = "JP2" + page_and_group_number; break; default: if (fileExtension.Length > 0) { thisFile.ID = fileExtension + page_and_group_number; } else { thisFile.ID = "NOEXT" + page_and_group_number; } break; } // Ensure this fileid is really unique. It may not be if there are multiple // files of the same mime-type in the same page. (such as 0001.jpg and 0001.qc.jpg) if (fileids_used.Contains(thisFile.ID)) { int count = 2; while (fileids_used.Contains(thisFile.ID + "." + count)) count++; thisFile.ID = thisFile.ID + "." + count; } // Save this file id fileids_used.Add(thisFile.ID); // Also add to the list of files allFiles.Add(thisFile); // Also ensure we know there are page image files hasPageFiles = true; // If this is a new MIME type, add it, else just save this file in the MIME hash if (!mimeHash.ContainsKey(mimetype)) { List<SobekCM_File_Info> newList = new List<SobekCM_File_Info> {thisFile}; mimeHash[mimetype] = newList; } else { mimeHash[mimetype].Add(thisFile); } } } // Prepare for the next page page_and_group_number++; } else { // Page has no files, so it should be skipped when written pageNode.ID = "SKIP"; } } else { // This node is a DIVISION (non-page) thisNode.ID = "PDIV" + division_number; division_number++; } } // Clear any existing ID's here since the ID's are only used for writing METS files foreach (abstract_TreeNode thisNode in downloadDivisions) { thisNode.ID = String.Empty; thisNode.DMDID = String.Empty; thisNode.ADMID = String.Empty; } // Now, do the same thing for the download/other files division tree // Group numbers in the METS file correspond to files on the same page (physical or other) // At the same time, we will build the list of all files and files by mime type page_and_group_number = 1; division_number = 1; foreach (abstract_TreeNode thisNode in downloadDivisions) { // If this node was already hit (perhaps if a div has two parent divs), // then skip it if (thisNode.ID.Length > 0) continue; // Add this to the list of all nodes allDivisions.Add(thisNode); // Was this a PAGE or a DIVISION node? if (thisNode.Page) { // Get this page node Page_TreeNode pageNode = (Page_TreeNode) thisNode; // Only do anything if there are actually any files here if ((pageNode.Files != null) && (pageNode.Files.Count > 0)) { // Set the page ID here pageNode.ID = "FILES" + page_and_group_number; // Step through any files under this page foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Set the ADMID and DMDID to empty in preparation for METS writing thisFile.ADMID = String.Empty; thisFile.DMDID = String.Empty; // If no file name, skip this if (String.IsNullOrEmpty(thisFile.System_Name)) continue; // Get this file extension and MIME type string fileExtension = thisFile.File_Extension; string mimetype = thisFile.MIME_Type(thisFile.File_Extension); // If this is going to be excluded from appearing in the METS file, just skip // it here as well. if (!mimes_to_exclude.Contains(mimetype)) { // Set the group number on this file thisFile.Group_Number = "G" + page_and_group_number; // Set the ID for this file as well switch (mimetype) { case "image/tiff": thisFile.ID = "TIF" + page_and_group_number; break; case "text/plain": thisFile.ID = "TXT" + page_and_group_number; break; case "image/jpeg": if (thisFile.System_Name.ToLower().IndexOf("thm.jp") > 0) { thisFile.ID = "THUMB" + page_and_group_number; mimetype = mimetype + "-thumbnails"; } else thisFile.ID = "JPEG" + page_and_group_number; break; case "image/gif": if (thisFile.System_Name.ToLower().IndexOf("thm.gif") > 0) { thisFile.ID = "THUMB" + page_and_group_number; mimetype = mimetype + "-thumbnails"; } else thisFile.ID = "GIF" + page_and_group_number; break; case "image/jp2": thisFile.ID = "JP2" + page_and_group_number; break; default: if (fileExtension.Length > 0) { thisFile.ID = fileExtension + page_and_group_number; } else { thisFile.ID = "NOEXT" + page_and_group_number; } break; } // Ensure this fileid is really unique. It may not be if there are multiple // files of the same mime-type in the same page. (such as 0001.jpg and 0001.qc.jpg) if (fileids_used.Contains(thisFile.ID)) { int count = 2; while (fileids_used.Contains(thisFile.ID + "." + count)) count++; thisFile.ID = thisFile.ID + "." + count; } // Save this file id fileids_used.Add(thisFile.ID); // Also add to the list of files allFiles.Add(thisFile); // Also ensure we know there are page image files hasDownloadFiles = true; // If this is a new MIME type, add it, else just save this file in the MIME hash if (!mimeHash.ContainsKey(mimetype)) { List<SobekCM_File_Info> newList = new List<SobekCM_File_Info> {thisFile}; mimeHash[mimetype] = newList; } else { mimeHash[mimetype].Add(thisFile); } } } // Prepare for the next page page_and_group_number++; } else { // Page has no files, so it should be skipped when written pageNode.ID = "SKIP"; } } else { // This node is a DIVISION (non-page) thisNode.ID = "ODIV" + division_number; division_number++; } } #endregion // Add the XML declaration Output_Stream.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>"); #region Write some processing instructions requested by Florida SUS's / FLVC (hope to deprecate) // Some special code for setting processing parameters bool daitssWriterIncluded = false; foreach (METS_Section_ReaderWriter_Config thisConfig in profile.Package_Level_AmdSec_Writer_Configs) { if (thisConfig.Code_Class == "DAITSS_METS_amdSec_ReaderWriter") { daitssWriterIncluded = true; break; } } if (daitssWriterIncluded) { DAITSS_Info daitssInfo = Item_To_Save.Get_Metadata_Module(GlobalVar.DAITSS_METADATA_MODULE_KEY) as DAITSS_Info; if (daitssInfo != null) { if ((daitssInfo.hasData) && (daitssInfo.toArchive)) { Output_Stream.WriteLine("<?fcla fda=\"yes\"?>"); } else { Output_Stream.WriteLine("<?fcla fda=\"no\"?>"); } } } #endregion // Add a remark here with the title and type Output_Stream.WriteLine("<!-- " + Item_To_Save.Bib_Info.Main_Title.Title_XML.Replace("-", " ") + " ( " + Item_To_Save.Bib_Info.SobekCM_Type_String + " ) -->"); // Add the METS declaration information Output_Stream.WriteLine("<METS:mets OBJID=\"" + Item_To_Save.METS_Header.ObjectID + "\""); Output_Stream.WriteLine(" xmlns:METS=\"http://www.loc.gov/METS/\""); Output_Stream.WriteLine(" xmlns:xlink=\"http://www.w3.org/1999/xlink\""); Output_Stream.WriteLine(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); #region Add XMLNS and schema locations for active METS section reader/writers with data to write // Collect all the xmlns and schema locations List<string> xmlnsList = new List<string>(); List<string> schemaLocList = new List<string>(); foreach (METS_Section_ReaderWriter_Config thisRWconfig in profile.Package_Level_AmdSec_Writer_Configs) { iPackage_amdSec_ReaderWriter thisRw = (iPackage_amdSec_ReaderWriter) thisRWconfig.ReaderWriterObject; if (thisRw.Schema_Reference_Required_Package(Item_To_Save)) { string[] rwXmlns = thisRw.Schema_Namespace(Item_To_Save); string[] rwSchema = thisRw.Schema_Location(Item_To_Save); foreach (string thisValue in rwXmlns) { if (!xmlnsList.Contains(thisValue)) xmlnsList.Add(thisValue); } foreach (string thisValue in rwSchema) { if (!schemaLocList.Contains(thisValue)) schemaLocList.Add(thisValue); } } } foreach (METS_Section_ReaderWriter_Config thisRWconfig in profile.Package_Level_DmdSec_Writer_Configs) { iPackage_dmdSec_ReaderWriter thisRw = (iPackage_dmdSec_ReaderWriter) thisRWconfig.ReaderWriterObject; if (thisRw.Schema_Reference_Required_Package(Item_To_Save)) { string[] rwXmlns = thisRw.Schema_Namespace(Item_To_Save); string[] rwSchema = thisRw.Schema_Location(Item_To_Save); foreach (string thisValue in rwXmlns) { if (!xmlnsList.Contains(thisValue)) xmlnsList.Add(thisValue); } foreach (string thisValue in rwSchema) { if (!schemaLocList.Contains(thisValue)) schemaLocList.Add(thisValue); } } } foreach (METS_Section_ReaderWriter_Config thisRWconfig in profile.Division_Level_AmdSec_Writer_Configs) { iDivision_amdSec_ReaderWriter thisRw = (iDivision_amdSec_ReaderWriter)thisRWconfig.ReaderWriterObject; foreach (abstract_TreeNode thisNode in physicalDivisions) { if (thisRw.Schema_Reference_Required_Division(thisNode)) { string[] rwXmlns = thisRw.Schema_Namespace(Item_To_Save); string[] rwSchema = thisRw.Schema_Location(Item_To_Save); foreach (string thisValue in rwXmlns) { if (!xmlnsList.Contains(thisValue)) xmlnsList.Add(thisValue); } foreach (string thisValue in rwSchema) { if (!schemaLocList.Contains(thisValue)) schemaLocList.Add(thisValue); } break; } } } foreach (METS_Section_ReaderWriter_Config thisRWconfig in profile.Division_Level_DmdSec_Writer_Configs) { iDivision_dmdSec_ReaderWriter thisRw = (iDivision_dmdSec_ReaderWriter)thisRWconfig.ReaderWriterObject; foreach (abstract_TreeNode thisNode in physicalDivisions) { if (thisRw.Schema_Reference_Required_Division(thisNode)) { string[] rwXmlns = thisRw.Schema_Namespace(Item_To_Save); string[] rwSchema = thisRw.Schema_Location(Item_To_Save); foreach (string thisValue in rwXmlns) { if (!xmlnsList.Contains(thisValue)) xmlnsList.Add(thisValue); } foreach (string thisValue in rwSchema) { if (!schemaLocList.Contains(thisValue)) schemaLocList.Add(thisValue); } break; } } } // Add the namespaces foreach (string namespaces in xmlnsList) { Output_Stream.WriteLine(" xmlns:" + namespaces); } Output_Stream.WriteLine(" xsi:schemaLocation=\"http://www.loc.gov/METS/"); Output_Stream.Write(" http://www.loc.gov/standards/mets/mets.xsd"); // Add the schema locations foreach (string location in schemaLocList) { Output_Stream.WriteLine(); Output_Stream.Write(location); } #endregion Output_Stream.WriteLine("\">"); // Add the METS declaration information and METS header Item_To_Save.METS_Header.Add_METS(Item_To_Save, Output_Stream); // Create the options dictionary for these writers Dictionary<string, object> options = new Dictionary<string, object>(); options["SobekCM_FileInfo_METS_amdSec_ReaderWriter:All_Files"] = allFiles; // Counters to keep track of the number of each section added int dmdSec_counter = 1; int digiProvMd = 1; int rightsMd = 1; int sourceMd = 1; int techMd = 1; #region Add all the package-level DMDSECs // Prepare to add all the bibliographic section StringBuilder dmd_secid_builder = new StringBuilder(); // Step through all the package level dmdSecs to be added foreach (METS_Section_ReaderWriter_Config thisConfig in profile.Package_Level_DmdSec_Writer_Configs) { iPackage_dmdSec_ReaderWriter thisWriter = (iPackage_dmdSec_ReaderWriter) thisConfig.ReaderWriterObject; if (thisWriter.Include_dmdSec(Item_To_Save, options)) { // Save this DMD ID dmd_secid_builder.Append("DMD" + dmdSec_counter + " "); // Start this METS section Output_Stream.WriteLine("<METS:dmdSec ID=\"DMD" + dmdSec_counter + "\">"); if (thisConfig.Default_Mapping.Other_MD_Type.Length > 0) Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" OTHERMDTYPE=\"" + thisConfig.Default_Mapping.Other_MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); else Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); Output_Stream.WriteLine("<METS:xmlData>"); // Add the amd section to the stream thisWriter.Write_dmdSec(Output_Stream, Item_To_Save, options); // Close this METS section Output_Stream.WriteLine("</METS:xmlData>"); Output_Stream.WriteLine("</METS:mdWrap>"); Output_Stream.WriteLine("</METS:dmdSec>"); dmdSec_counter++; } } // Now, add any unanalyzed DMD sections if (( Item_To_Save.Unanalyzed_DMDSECs != null ) && ( Item_To_Save.Unanalyzed_DMDSECs.Count > 0 )) { foreach (Unanalyzed_METS_Section thisSection in Item_To_Save.Unanalyzed_DMDSECs) { // This wll be linked to the top-level dmd_secid_builder.Append("DMD" + dmdSec_counter + " "); // Add this to the output stream Output_Stream.Write("<METS:dmdSec ID=\"DMD" + dmdSec_counter + "\""); foreach (KeyValuePair<string, string> attribute in thisSection.Section_Attributes) { if (attribute.Key != "ID") Output_Stream.Write(" " + attribute.Key + "=\"" + attribute.Value + "\""); } Output_Stream.WriteLine(">"); Output_Stream.WriteLine(thisSection.Inner_XML); Output_Stream.WriteLine("</METS:dmdSec>"); dmdSec_counter++; } } #endregion #region Add all the division-level DMDSECs // Should we add DMDSEC metadata sections for the divisions? // Step through all the possible division level dmdSecs to be added foreach (METS_Section_ReaderWriter_Config thisConfig in profile.Division_Level_DmdSec_Writer_Configs) { // Step through each division foreach (abstract_TreeNode thisDivision in allDivisions) { iDivision_dmdSec_ReaderWriter thisWriter = (iDivision_dmdSec_ReaderWriter) thisConfig.ReaderWriterObject; // Include the DMD Sec for this division? if (thisWriter.Include_dmdSec(thisDivision, options)) { // Save this DMD ID thisDivision.DMDID = thisDivision.DMDID + "DMD" + dmdSec_counter + " "; // Start this METS section Output_Stream.WriteLine("<METS:dmdSec ID=\"DMD" + dmdSec_counter + "\">"); if (thisConfig.Default_Mapping.Other_MD_Type.Length > 0) Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" OTHERMDTYPE=\"" + thisConfig.Default_Mapping.Other_MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); else Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); Output_Stream.WriteLine("<METS:xmlData>"); // Add the amd section to the stream thisWriter.Write_dmdSec(Output_Stream, thisDivision, options); // Close this METS section Output_Stream.WriteLine("</METS:xmlData>"); Output_Stream.WriteLine("</METS:mdWrap>"); Output_Stream.WriteLine("</METS:dmdSec>"); dmdSec_counter++; } } } #endregion #region Add all the file-level DMDSECs // Should we add DMDSEC metadata sections for the files? // Step through all the possible file level dmdSecs to be added foreach (METS_Section_ReaderWriter_Config thisConfig in profile.File_Level_DmdSec_Writer_Configs) { // Step through each file foreach (SobekCM_File_Info thisFile in allFiles) { iFile_dmdSec_ReaderWriter thisWriter = (iFile_dmdSec_ReaderWriter)thisConfig.ReaderWriterObject; // Include the DMD Sec for this file? if (thisWriter.Include_dmdSec(thisFile, options)) { // Save this DMD ID thisFile.DMDID = thisFile.DMDID + "DMD" + dmdSec_counter + " "; // Start this METS section Output_Stream.WriteLine("<METS:dmdSec ID=\"DMD" + dmdSec_counter + "\">"); if (thisConfig.Default_Mapping.Other_MD_Type.Length > 0) Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" OTHERMDTYPE=\"" + thisConfig.Default_Mapping.Other_MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); else Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); Output_Stream.WriteLine("<METS:xmlData>"); // Add the amd section to the stream thisWriter.Write_dmdSec(Output_Stream, thisFile, options); // Close this METS section Output_Stream.WriteLine("</METS:xmlData>"); Output_Stream.WriteLine("</METS:mdWrap>"); Output_Stream.WriteLine("</METS:dmdSec>"); dmdSec_counter++; } } } #endregion #region Add all the package-level AMDSECs // Prepare to add all the bibliographic section StringBuilder amd_secid_builder = new StringBuilder(); // Step through all the package level amdSecs to be added foreach (METS_Section_ReaderWriter_Config thisConfig in profile.Package_Level_AmdSec_Writer_Configs) { iPackage_amdSec_ReaderWriter thisWriter = (iPackage_amdSec_ReaderWriter)thisConfig.ReaderWriterObject; if (thisWriter.Include_amdSec(Item_To_Save, options)) { // Start this METS section Output_Stream.WriteLine("<METS:amdSec>"); switch (thisConfig.AmdSecType) { case METS_amdSec_Type_Enum.DigiProvMD: Output_Stream.WriteLine("<METS:digiprovMD ID=\"DIGIPROV" + digiProvMd + "\">"); amd_secid_builder.Append("DIGIPROV" + digiProvMd + " "); digiProvMd++; break; case METS_amdSec_Type_Enum.RightsMD: Output_Stream.WriteLine("<METS:rightsMD ID=\"RIGHTS" + rightsMd + "\">"); amd_secid_builder.Append("RIGHTS" + rightsMd + " "); rightsMd++; break; case METS_amdSec_Type_Enum.SourceMD: Output_Stream.WriteLine("<METS:sourceMD ID=\"SOURCE" + sourceMd + "\">"); amd_secid_builder.Append("SOURCE" + sourceMd + " "); sourceMd++; break; case METS_amdSec_Type_Enum.TechMD: Output_Stream.WriteLine("<METS:techMD ID=\"TECH" + techMd + "\">"); amd_secid_builder.Append("TECH" + techMd + " "); techMd++; break; default: Output_Stream.WriteLine("<METS:rightsMD ID=\"RIGHTS" + rightsMd + "\">"); amd_secid_builder.Append("RIGHTS" + rightsMd + " "); rightsMd++; break; } if (thisConfig.Default_Mapping.Other_MD_Type.Length > 0) Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" OTHERMDTYPE=\"" + thisConfig.Default_Mapping.Other_MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); else Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); Output_Stream.WriteLine("<METS:xmlData>"); // Add the amd section to the stream thisWriter.Write_amdSec(Output_Stream, Item_To_Save, options); // Close this METS section Output_Stream.WriteLine("</METS:xmlData>"); Output_Stream.WriteLine("</METS:mdWrap>"); switch (thisConfig.AmdSecType) { case METS_amdSec_Type_Enum.DigiProvMD: Output_Stream.WriteLine("</METS:digiprovMD>"); break; case METS_amdSec_Type_Enum.RightsMD: Output_Stream.WriteLine("</METS:rightsMD>"); break; case METS_amdSec_Type_Enum.SourceMD: Output_Stream.WriteLine("</METS:sourceMD>"); break; case METS_amdSec_Type_Enum.TechMD: Output_Stream.WriteLine("</METS:techMD>"); break; default: Output_Stream.WriteLine("</METS:rightsMD>"); break; } Output_Stream.WriteLine("</METS:amdSec>"); } } // Now, add any unanalyzed AMD sections if (Item_To_Save.Unanalyzed_AMDSECs != null) { foreach (Unanalyzed_METS_Section thisSection in Item_To_Save.Unanalyzed_AMDSECs) { // Add this to the output stream Output_Stream.Write("<METS:amdSec"); foreach (KeyValuePair<string, string> attribute in thisSection.Section_Attributes) { if (attribute.Key != "ID") Output_Stream.Write(" " + attribute.Key + "=\"" + attribute.Value + "\""); } Output_Stream.WriteLine(">"); Output_Stream.WriteLine(thisSection.Inner_XML); Output_Stream.WriteLine("</METS:amdSec>"); } } #endregion #region Add all the division-level AMDSECs // Should we add AMDSEC metadata sections for the divisions? // Step through all the possible division level amdSecs to be added foreach (METS_Section_ReaderWriter_Config thisConfig in profile.Division_Level_AmdSec_Writer_Configs) { // Step through each division foreach (abstract_TreeNode thisDivision in allDivisions) { iDivision_amdSec_ReaderWriter thisWriter = (iDivision_amdSec_ReaderWriter) thisConfig.ReaderWriterObject; // Include the DMD Sec for this division? if (thisWriter.Include_amdSec(thisDivision, options)) { // Start this METS section Output_Stream.WriteLine("<METS:amdSec>"); switch (thisConfig.AmdSecType) { case METS_amdSec_Type_Enum.DigiProvMD: Output_Stream.WriteLine("<METS:digiProvMD ID=\"DIGIPROV" + digiProvMd + "\">"); thisDivision.ADMID = thisDivision.ADMID + "DIGIPROV" + digiProvMd + " "; digiProvMd++; break; case METS_amdSec_Type_Enum.RightsMD: Output_Stream.WriteLine("<METS:rightsMD ID=\"RIGHTS" + rightsMd + "\">"); thisDivision.ADMID = thisDivision.ADMID + "RIGHTS" + rightsMd + " "; rightsMd++; break; case METS_amdSec_Type_Enum.SourceMD: Output_Stream.WriteLine("<METS:sourceMD ID=\"SOURCE" + sourceMd + "\">"); thisDivision.ADMID = thisDivision.ADMID + "SOURCE" + sourceMd + " "; sourceMd++; break; case METS_amdSec_Type_Enum.TechMD: Output_Stream.WriteLine("<METS:techMD ID=\"TECH" + techMd + "\">"); thisDivision.ADMID = thisDivision.ADMID + "TECH" + techMd + " "; techMd++; break; default: Output_Stream.WriteLine("<METS:rightsMD ID=\"RIGHTS" + rightsMd + "\">"); thisDivision.ADMID = thisDivision.ADMID + "RIGHTS" + rightsMd + " "; rightsMd++; break; } if (thisConfig.Default_Mapping.Other_MD_Type.Length > 0) Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" OTHERMDTYPE=\"" + thisConfig.Default_Mapping.Other_MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); else Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); Output_Stream.WriteLine("<METS:xmlData>"); Output_Stream.WriteLine("<METS:xmlData>"); // Add the amd section to the stream thisWriter.Write_amdSec(Output_Stream, thisDivision, options); // Close this METS section Output_Stream.WriteLine("</METS:xmlData>"); Output_Stream.WriteLine("</METS:mdWrap>"); switch (thisConfig.AmdSecType) { case METS_amdSec_Type_Enum.DigiProvMD: Output_Stream.WriteLine("</METS:digiProvMD>"); break; case METS_amdSec_Type_Enum.RightsMD: Output_Stream.WriteLine("</METS:rightsMD>"); break; case METS_amdSec_Type_Enum.SourceMD: Output_Stream.WriteLine("</METS:sourceMD>"); break; case METS_amdSec_Type_Enum.TechMD: Output_Stream.WriteLine("</METS:techMD>"); break; default: Output_Stream.WriteLine("</METS:rightsMD>"); break; } Output_Stream.WriteLine("</METS:amdSec>"); dmdSec_counter++; } } } #endregion #region Add all the file-level AMDSECs // Should we add AMDSEC metadata sections for the files? // Step through all the possible file level amdSecs to be added foreach (METS_Section_ReaderWriter_Config thisConfig in profile.File_Level_AmdSec_Writer_Configs) { // Step through each file foreach (SobekCM_File_Info thisFile in allFiles) { iFile_amdSec_ReaderWriter thisWriter = (iFile_amdSec_ReaderWriter)thisConfig.ReaderWriterObject; // Include the DMD Sec for this file? if (thisWriter.Include_amdSec(thisFile, options)) { // Start this METS section Output_Stream.WriteLine("<METS:amdSec>"); switch (thisConfig.AmdSecType) { case METS_amdSec_Type_Enum.DigiProvMD: Output_Stream.WriteLine("<METS:digiProvMD ID=\"DIGIPROV" + digiProvMd + "\">"); thisFile.ADMID = thisFile.ADMID + "DIGIPROV" + digiProvMd + " "; digiProvMd++; break; case METS_amdSec_Type_Enum.RightsMD: Output_Stream.WriteLine("<METS:rightsMD ID=\"RIGHTS" + rightsMd + "\">"); thisFile.ADMID = thisFile.ADMID + "RIGHTS" + rightsMd + " "; rightsMd++; break; case METS_amdSec_Type_Enum.SourceMD: Output_Stream.WriteLine("<METS:sourceMD ID=\"SOURCE" + sourceMd + "\">"); thisFile.ADMID = thisFile.ADMID + "SOURCE" + sourceMd + " "; sourceMd++; break; case METS_amdSec_Type_Enum.TechMD: Output_Stream.WriteLine("<METS:techMD ID=\"TECH" + techMd + "\">"); thisFile.ADMID = thisFile.ADMID + "TECH" + techMd + " "; techMd++; break; default: Output_Stream.WriteLine("<METS:rightsMD ID=\"RIGHTS" + rightsMd + "\">"); thisFile.ADMID = thisFile.ADMID + "RIGHTS" + rightsMd + " "; rightsMd++; break; } if (thisConfig.Default_Mapping.Other_MD_Type.Length > 0) Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" OTHERMDTYPE=\"" + thisConfig.Default_Mapping.Other_MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); else Output_Stream.WriteLine("<METS:mdWrap MDTYPE=\"" + thisConfig.Default_Mapping.MD_Type + "\" MIMETYPE=\"text/xml\" LABEL=\"" + thisConfig.Default_Mapping.Label + "\">"); Output_Stream.WriteLine("<METS:xmlData>"); Output_Stream.WriteLine("<METS:xmlData>"); // Add the amd section to the stream thisWriter.Write_amdSec(Output_Stream, thisFile, options); // Close this METS section Output_Stream.WriteLine("</METS:xmlData>"); Output_Stream.WriteLine("</METS:mdWrap>"); switch (thisConfig.AmdSecType) { case METS_amdSec_Type_Enum.DigiProvMD: Output_Stream.WriteLine("</METS:digiProvMD>"); break; case METS_amdSec_Type_Enum.RightsMD: Output_Stream.WriteLine("</METS:rightsMD>"); break; case METS_amdSec_Type_Enum.SourceMD: Output_Stream.WriteLine("</METS:sourceMD>"); break; case METS_amdSec_Type_Enum.TechMD: Output_Stream.WriteLine("</METS:techMD>"); break; default: Output_Stream.WriteLine("</METS:rightsMD>"); break; } Output_Stream.WriteLine("</METS:amdSec>"); dmdSec_counter++; } } } #endregion // Add file and structure map sections if ( allFiles.Count > 0 ) { #region Add the files section // Start the files section Output_Stream.WriteLine("<METS:fileSec>"); // Step through each mime type foreach (string thisMimeType in mimeHash.Keys) { List<SobekCM_File_Info> mimeCollection = mimeHash[thisMimeType]; // Start this file group section Output_Stream.WriteLine(thisMimeType == "image/tiff" ? "<METS:fileGrp USE=\"archive\" >" : "<METS:fileGrp USE=\"reference\" >"); // Step through each file of this mime type and append the METS foreach (SobekCM_File_Info thisFile in mimeCollection) { // Is the size and checksum information here? if ((!MINIMIZE_FILE_SIZE) && ( !Item_To_Save.Divisions.Suppress_Checksum )) { if ((((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0))) && (thisFile.METS_LocType == SobekCM_File_Info_Type_Enum.SYSTEM)) { // Perform in a try catch try { if (File.Exists(Item_To_Save.Source_Directory + "/" + thisFile.System_Name)) { // Get the size first if ( thisFile.Size < 0 ) { FileInfo thisFileInfo = new FileInfo(Item_To_Save.Source_Directory + "/" + thisFile.System_Name); thisFile.Size = thisFileInfo.Length; } // Get the checksum, if it doesn't exist if (String.IsNullOrEmpty(thisFile.Checksum)) { FileMD5 checksummer = new FileMD5(Item_To_Save.Source_Directory + "/" + thisFile.System_Name); thisFile.Checksum = checksummer.Checksum; // Set the checksum type thisFile.Checksum_Type = "MD5"; } } } catch { } } } // Start out this file Output_Stream.Write("<METS:file GROUPID=\"" + thisFile.Group_Number + "\" ID=\"" + thisFile.ID + "\" MIMETYPE=\"" + thisMimeType + "\""); // Add links to dmd secs and amd secs if (!String.IsNullOrEmpty(thisFile.DMDID)) { Output_Stream.Write(" DMDID=\"" + thisFile.DMDID + "\""); } if (!String.IsNullOrEmpty(thisFile.ADMID)) { Output_Stream.Write(" ADMID=\"" + thisFile.ADMID + "\""); } // Add the checksum it it exists if ((!MINIMIZE_FILE_SIZE) && (!String.IsNullOrEmpty(thisFile.Checksum))) { Output_Stream.Write(" CHECKSUM=\"" + thisFile.Checksum + "\""); // Add the checksum type if there was one (SHOULD be one here) if (!String.IsNullOrEmpty(thisFile.Checksum_Type)) { Output_Stream.Write(" CHECKSUMTYPE=\"" + thisFile.Checksum_Type + "\""); } } // Add the size of the file, if it exists if ((!MINIMIZE_FILE_SIZE) && (thisFile.Size > 0)) { Output_Stream.Write(" SIZE=\"" + thisFile.Size + "\""); } // Close out this beginning file tag Output_Stream.WriteLine(">"); // Include the system name or URL if (thisFile.METS_LocType == SobekCM_File_Info_Type_Enum.URL) { Output_Stream.WriteLine("<METS:FLocat LOCTYPE=\"URL\" xlink:href=\"" + thisFile.System_Name.Replace(" ", "%20").Replace("&", "&") + "\" />"); } else { Output_Stream.WriteLine("<METS:FLocat LOCTYPE=\"OTHER\" OTHERLOCTYPE=\"SYSTEM\" xlink:href=\"" + thisFile.System_Name.Replace(" ", "%20").Replace("&", "&").Replace("\\", "/") + "\" />"); } // Add the closing file tag Output_Stream.WriteLine("</METS:file>"); } // Close out this file group section Output_Stream.WriteLine("</METS:fileGrp>"); } // Finish out the file section Output_Stream.WriteLine("</METS:fileSec>"); #endregion #region Add the structure map section Dictionary<abstract_TreeNode, int> pages_to_appearances = new Dictionary<abstract_TreeNode, int>(); // May or may not be AMDSecs and DMDsec string dmdSecIdString = dmd_secid_builder.ToString().Trim(); string amdSecIdString = amd_secid_builder.ToString().Trim(); // Add the physical page structure map first if (hasPageFiles) { Output_Stream.WriteLine("<METS:structMap ID=\"STRUCT1\" TYPE=\"physical\">"); // Add any outer divisions here if ( Item_To_Save.Divisions.Outer_Division_Count > 0) { foreach (Outer_Division_Info outerDiv in Item_To_Save.Divisions.Outer_Divisions) { Output_Stream.Write("<METS:div"); if (dmdSecIdString.Length > 0) { Output_Stream.Write(" DMDID=\"" + dmdSecIdString + "\""); } if (outerDiv.Label.Length > 0) { Output_Stream.Write(" LABEL=\"" + Convert_String_To_XML_Safe_Static(outerDiv.Label) + "\""); } if (outerDiv.OrderLabel > 0) { Output_Stream.Write(" ORDERLABEL=\"" + outerDiv.OrderLabel + "\""); } if (outerDiv.Type.Length > 0) { Output_Stream.Write(" TYPE=\"" + Convert_String_To_XML_Safe_Static(outerDiv.Type) + "\""); } Output_Stream.WriteLine(">"); } } else { // Start the main division information Output_Stream.Write("<METS:div"); if (dmdSecIdString.Length > 0) { Output_Stream.Write(" DMDID=\"" + dmdSecIdString + "\""); } if (amdSecIdString.Length > 0) { Output_Stream.Write(" ADMID=\"" + amdSecIdString + "\""); } // Add the title, if one was provided string title = Item_To_Save.Bib_Info.Main_Title.ToString(); if (title.Length > 0) { Output_Stream.Write(" LABEL=\"" + title + "\""); } // Finish out this first, main division tag Output_Stream.WriteLine(" ORDER=\"0\" TYPE=\"main\">"); } // Add all the divisions recursively int order = 1; foreach (abstract_TreeNode thisRoot in Item_To_Save.Divisions.Physical_Tree.Roots) { recursively_add_div_info(thisRoot, Output_Stream, pages_to_appearances, order++); } // Close any outer divisions here if (Item_To_Save.Divisions.Outer_Division_Count > 0) { for (int index = 0; index < Item_To_Save.Divisions.Outer_Division_Count; index++) { Output_Stream.WriteLine("</METS:div>"); } } else { // Close out the main division tag Output_Stream.WriteLine("</METS:div>"); } // Close out this structure map portion Output_Stream.WriteLine("</METS:structMap>"); } if (hasDownloadFiles) { Output_Stream.WriteLine("<METS:structMap ID=\"STRUCT2\" TYPE=\"other\">"); // Add any outer divisions here if ( Item_To_Save.Divisions.Outer_Division_Count > 0) { foreach (Outer_Division_Info outerDiv in Item_To_Save.Divisions.Outer_Divisions) { Output_Stream.Write("<METS:div"); if (dmdSecIdString.Length > 0) { Output_Stream.Write(" DMDID=\"" + dmdSecIdString + "\""); } if (outerDiv.Label.Length > 0) { Output_Stream.Write(" LABEL=\"" + Convert_String_To_XML_Safe_Static(outerDiv.Label) + "\""); } if (outerDiv.OrderLabel > 0) { Output_Stream.Write(" ORDERLABEL=\"" + outerDiv.OrderLabel + "\""); } if (outerDiv.Type.Length > 0) { Output_Stream.Write(" TYPE=\"" + Convert_String_To_XML_Safe_Static(outerDiv.Type) + "\""); } Output_Stream.WriteLine(">"); } } else { // Start the main division information Output_Stream.Write("<METS:div"); if (dmdSecIdString.Length > 0) { Output_Stream.Write(" DMDID=\"" + dmdSecIdString + "\""); } if (amdSecIdString.Length > 0) { Output_Stream.Write(" ADMID=\"" + amdSecIdString + "\""); } // Add the title, if one was provided string title = Item_To_Save.Bib_Info.Main_Title.ToString(); if (title.Length > 0) { Output_Stream.Write(" LABEL=\"" + title + "\""); } // Finish out this first, main division tag Output_Stream.WriteLine(" ORDER=\"0\" TYPE=\"main\">"); } // Add all the divisions recursively int order = 1; foreach (abstract_TreeNode thisRoot in Item_To_Save.Divisions.Download_Tree.Roots) { recursively_add_div_info(thisRoot, Output_Stream, pages_to_appearances, order++); } // Close any outer divisions here if (Item_To_Save.Divisions.Outer_Division_Count > 0) { for (int index = 0; index < Item_To_Save.Divisions.Outer_Division_Count; index++) { Output_Stream.WriteLine("</METS:div>"); } } else { // Close out the main division tag Output_Stream.WriteLine("</METS:div>"); } // Close out this structure map portion Output_Stream.WriteLine("</METS:structMap>"); } #endregion } else { // Structure map is a required element for METS Output_Stream.Write("<METS:structMap ID=\"STRUCT1\" > <METS:div /> </METS:structMap>\r\n"); } // Add the behavior section for SobekCM views and interfaces //if (embedded_metadata_types.Contains(Metadata_Type_Enum.SobekCM_Behaviors)) //{ // Item_To_Save.Behaviors.Add_BehaviorSec_METS(Output, Item_To_Save.Divisions.Physical_Tree.Has_Files); //} // Close out the METS file Output_Stream.Write("</METS:mets>\r\n"); return true; }
/// <summary> Recalculates all the checksums for associated files </summary> /// <param name="Recalculate_All"> Flag indicates whether to recalculate all files, regardless of need </param> /// <param name="Progress_Delegate"> Progress delegate is called to update any progress displays </param> public void Calculate_Checksum(bool Recalculate_All, New_SobekCM_Bib_Package_Progress_Task_Group Progress_Delegate) { // Get the list of all pages from this division trees List <abstract_TreeNode> pageNodes = physicalDivisionTree.Pages_PreOrder; List <abstract_TreeNode> fileNodes = downloadDivisionTree.Pages_PreOrder; // Update progress if (Progress_Delegate != null) { Progress_Delegate("Calculating checksums", "Checking all files", 0, 2); } // Count how many pages to calculate for int total_files = 0; foreach (Page_TreeNode pageNode in pageNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0))) { total_files++; } } } foreach (Page_TreeNode pageNode in fileNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0))) { total_files++; } } } if (total_files == 0) { return; } // Now caulcate int file_count = 0; FileMD5 checksummer = new FileMD5(); foreach (Page_TreeNode pageNode in pageNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((thisFile.METS_LocType == SobekCM_File_Info_Type_Enum.SYSTEM) && ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0)))) { // Perform in a try catch try { // Get the size first FileInfo thisFileInfo = new FileInfo(source_directory + "/" + thisFile.System_Name); thisFile.Size = thisFileInfo.Length; // Get the checksum, if it doesn't exist if ((String.IsNullOrEmpty(thisFile.Checksum)) || (Recalculate_All)) { thisFile.Checksum = checksummer.Calculate_Checksum(source_directory + "/" + thisFile.System_Name); thisFile.Checksum_Type = "MD5"; } } catch {} file_count++; // Update progress if (Progress_Delegate != null) { Progress_Delegate("Calculating checksums", "Calculating '" + thisFile.System_Name + "'", file_count, total_files); } } } } foreach (Page_TreeNode pageNode in fileNodes) { // Step through each file foreach (SobekCM_File_Info thisFile in pageNode.Files) { // Recalculate this file info? if ((thisFile.METS_LocType == SobekCM_File_Info_Type_Enum.SYSTEM) && ((Recalculate_All) || ((String.IsNullOrEmpty(thisFile.Checksum)) || (thisFile.Size <= 0)))) { // Perform in a try catch try { // Get the size first FileInfo thisFileInfo = new FileInfo(source_directory + "/" + thisFile.System_Name); thisFile.Size = thisFileInfo.Length; // Get the checksum, if it doesn't exist if ((String.IsNullOrEmpty(thisFile.Checksum)) || (Recalculate_All)) { thisFile.Checksum = checksummer.Calculate_Checksum(source_directory + "/" + thisFile.System_Name); thisFile.Checksum_Type = "MD5"; } } catch {} file_count++; // Update progress if (Progress_Delegate != null) { Progress_Delegate("Calculating checksums", "Calculating '" + thisFile.System_Name + "'", file_count, total_files); } } } } // Update progress if (Progress_Delegate != null) { Progress_Delegate("Checksum Complete", "Checksum Complete", file_count, total_files); } }