private static void read_struct_map(XmlReader R, SobekCM_Item Package, Dictionary<string, SobekCM_File_Info> FilesByFileid, Dictionary<string, abstract_TreeNode> DivisionDmdids, Dictionary<string, abstract_TreeNode> DivisionAmdids )
{
Stack<abstract_TreeNode> parentNodes = new Stack<abstract_TreeNode>();
Dictionary<string, abstract_TreeNode> divisions_by_id = new Dictionary<string, abstract_TreeNode>();
bool mainDivisionFound = false;
Division_Tree thisDivTree = null;
// Loop through reading each XML node
do
{
// get the right division information based on node type
switch (R.NodeType)
{
// if EndElement, move up tree
case XmlNodeType.EndElement:
if ((R.Name == "METS:structMap") || ( R.Name == "structMap" ))
{
return;
}
if ((R.Name == "METS:div") || (R.Name == "div"))
{
// If there are more than one parent on the "parent stack" pop one off
if (parentNodes.Count > 0)
parentNodes.Pop();
}
break;
// if new element, add name and traverse tree
case XmlNodeType.Element:
// Is this the beginning of a structure map
if ((R.Name == "METS:structMap") || (R.Name == "structMap"))
{
thisDivTree = Package.Divisions.Physical_Tree;
if (R.MoveToAttribute("TYPE"))
{
if (R.Value.ToUpper() == "OTHER")
thisDivTree = Package.Divisions.Download_Tree;
}
}
// Is this a new division?
if (((R.Name == "METS:div") || ( R.Name == "div" )) && (R.HasAttributes))
{
// Since this is a new division, get all the possible attribute values or set to empty string
string dmdid = (R.MoveToAttribute("DMDID") ? R.Value : String.Empty);
string amdid = (R.MoveToAttribute("AMDID") ? R.Value : String.Empty);
string divID = (R.MoveToAttribute("DMDID") ? R.Value : String.Empty);
string divType = (R.MoveToAttribute("TYPE") ? R.Value : String.Empty);
string divLabel = (R.MoveToAttribute("LABEL") ? R.Value : String.Empty);
// Get the order
ushort divOrder;
if (R.MoveToAttribute("ORDER"))
{
if (!UInt16.TryParse(R.Value, out divOrder)) divOrder = 0;
}
else if (R.MoveToAttribute("ORDERLABEL"))
{
if (!UInt16.TryParse(R.Value, out divOrder)) divOrder = 0;
}
else
{
divOrder = 0;
}
// Was this an outer division, or the main division?
if (!mainDivisionFound)
{
// This is an outer wrapper and NOT the MAIN division, so save this as an
// outer division (division greater than current digital resources), such as
// used sometimes for serials or journals.
if (divType.ToUpper() != "MAIN")
{
if (!Package.Divisions.Contains_Outer_Division(divLabel, divType))
{
Package.Divisions.Add_Outer_Division(divLabel, divOrder, divType);
}
}
else
{
mainDivisionFound = true;
}
}
else
{
// Get the parent node, if there is one
abstract_TreeNode parentNode = parentNodes.Count > 0 ? parentNodes.Peek() : null;
// Create this division
abstract_TreeNode bibNode;
if (divType.ToUpper() == "PAGE")
bibNode = new Page_TreeNode(divLabel);
else
bibNode = new Division_TreeNode(divType, divLabel);
// Check to make sure no repeat here
if (divID.IndexOf("_repeat") > 0)
{
divID = divID.Substring(0, divID.IndexOf("_repeat"));
if (divisions_by_id.ContainsKey(divID))
{
bibNode = divisions_by_id[divID];
}
}
// Get the DMD sec or AMD sec's
if (dmdid.Length > 0)
{
string[] divDmdSecIds = dmdid.Split(" ".ToCharArray());
foreach( string thisId in divDmdSecIds )
{
DivisionDmdids[thisId] = bibNode;
}
}
if (amdid.Length > 0)
{
string[] divAmdSecIds = amdid.Split(" ".ToCharArray());
foreach (string thisId in divAmdSecIds)
{
DivisionAmdids[thisId] = bibNode;
}
}
// If there is a parent, add to it
if (parentNode != null)
{
((Division_TreeNode) parentNode).Nodes.Add(bibNode);
}
else
{
// No parent, so add this to the root
thisDivTree.Roots.Add(bibNode);
}
// Now, add this to the end of the parent list, in case it has children
if (!R.IsEmptyElement)
{
parentNodes.Push(bibNode);
}
}
R.MoveToElement();
}
// Is this a new file pointer applying to the last division?
if (((R.Name == "METS:fptr") || (R.Name == "fptr")) && (R.MoveToAttribute("FILEID")))
{
// Get this file id
string fileID = R.Value;
// Get the file from the files by id dictionary
if (FilesByFileid.ContainsKey(fileID))
{
SobekCM_File_Info thisFile = FilesByFileid[fileID];
abstract_TreeNode pageParentNode = null;
if (parentNodes.Count > 0)
pageParentNode = parentNodes.Peek();
if ((pageParentNode != null) && (pageParentNode.Page))
{
Page_TreeNode asPageNode = (Page_TreeNode) pageParentNode;
if (!asPageNode.Files.Contains(thisFile))
asPageNode.Files.Add(thisFile);
}
else
{
if (pageParentNode == null)
{
thisDivTree.Add_File(thisFile);
}
else
{
Division_TreeNode asDivNode = (Division_TreeNode) pageParentNode;
Page_TreeNode newPage = new Page_TreeNode();
asDivNode.Add_Child(newPage);
//parentNodes.Push(newPage);
newPage.Files.Add(thisFile);
}
}
}
}
// Is this a new METS pointer, often seen when importing from DSpace
if ((R.Name == "METS:mptr") || (R.Name == "mptr"))
{
// Get the parent label
string parentLabel = String.Empty;
// Look for a parent node (should be one)
if (parentNodes.Count > 0)
{
abstract_TreeNode pageParentNode = parentNodes.Peek();
parentLabel = pageParentNode.Label;
}
else if (Package.Divisions.Outer_Division_Count > 0)
{
parentLabel = Package.Divisions.Outer_Divisions[Package.Divisions.Outer_Division_Count - 1].Label;
}
if ((!String.IsNullOrEmpty(parentLabel)) && (String.Compare(parentLabel, "Parent of this DSpace Object", StringComparison.OrdinalIgnoreCase) == 0))
{
// Is this a HANDLE reference?
string locType = (R.MoveToAttribute("LOCTYPE") ? R.Value : String.Empty).ToUpper();
string href = (R.MoveToAttribute("xlink:href") ? R.Value : String.Empty);
// If this has a handle href, make that the aggregation
if ((locType == "HANDLE") && (href.Length > 0))
{
Package.Behaviors.Add_Aggregation(href);
}
}
}
break;
} // end switch
} while (R.Read());
}