function [ files ] = s1manifest_files( domnode )
%S1MANIFEST_FILES Extract relevant measurement and metadata files from a
%Sentinel manifest.safe file and group them together appropriately.
%
% Written by: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

%% Setup
% Overall wrapping node is in a namespace that makes things messier
% (than they already are) in a XPath call, so we go down one level.
domnode = domnode.getFirstChild;
xp=javax.xml.xpath.XPathFactory.newInstance.newXPath();

%% Find associated measurement and metadata files in this package
% First find all of the "Measurement Data Units".  This should provide each
% data object (measurements), together with its metadata and noise and
% calibration files.
mdu_xp_str = ['informationPackageMap/' ...
    '*[local-name()=''contentUnit'']/' ...
    '*[local-name()=''contentUnit''][@repID="s1Level1MeasurementSchema"]'];
num_measurment_data_units = str2double(xp.evaluate(...
    ['count(' mdu_xp_str ')'],...
    domnode));
files(num_measurment_data_units) = struct('data','','product','','noise','','calibration','');
for i = 1:num_measurment_data_units
    % Find data ("measurement") file itself
    data_object_ID = char(xp.evaluate(...
        [mdu_xp_str '[' num2str(i) ']/dataObjectPointer/@dataObjectID'],domnode));
    files(i).data = char(xp.evaluate([...
        'dataObjectSection/' ...
        'dataObject[@ID="' data_object_ID '"]/' ...
        'byteStream/' ...
        'fileLocation/' ...
        '@href'],domnode));
    % Find references to associated metadata files
    associated_DMDs = strsplit(strtrim(char(xp.evaluate(...
        [mdu_xp_str '[' num2str(i) ']/@dmdID'],domnode))));
    % The references are indirect.  They are equivalently pointers to
    % pointers. Not clear why it was done this way, but here we get the
    % real IDs for those files (used in the dataObjectSection).
    associated_IDs=cell(numel(associated_DMDs),1);
    for j = 1:numel(associated_DMDs)
        associated_IDs{j} = char(xp.evaluate([
            'metadataSection/' ...
            'metadataObject[@ID="' associated_DMDs{j} '"]/' ...
            'dataObjectPointer/' ...
            '@dataObjectID'],domnode));
    end
    % Construct a string that will look for any of these IDs
    ID_test_string = ['[@ID="' associated_IDs{1} '"'];
    for j = 2:numel(associated_IDs)
        ID_test_string = [ID_test_string ' or @ID="' associated_IDs{j} '"'];
    end
    ID_test_string = [ID_test_string ']'];
    files(i).product = char(xp.evaluate([...
        'dataObjectSection/' ...
        'dataObject[@repID="s1Level1ProductSchema"]' ... % Must be product type
        ID_test_string '/' ... % and an ID that matches one associated with the current measurement
        'byteStream/' ...
        'fileLocation/' ...
        '@href'],domnode));
    files(i).noise = char(xp.evaluate([...
        'dataObjectSection/' ...
        'dataObject[@repID="s1Level1NoiseSchema"]' ... % Must be noise type
        ID_test_string '/' ... % and an ID that matches one associated with the current measurement
        'byteStream/' ...
        'fileLocation/' ...
        '@href'],domnode));
    files(i).calibration = char(xp.evaluate([...
        'dataObjectSection/' ...
        'dataObject[@repID="s1Level1CalibrationSchema"]' ... % Must be calibration type
        ID_test_string '/' ... % and an ID that matches one associated with the current measurement
        'byteStream/' ...
        'fileLocation/' ...
        '@href'],domnode));
end

% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////