function reqInfoOut = prepReqInfoForSave(this)
% Prepare reqInfo to be attached to cvdata.
% Removes fields from reqInfo which can't be saved in the cov db.

    reqInfoTemplate = struct(...
        'Requirement', struct(...
            'Label',[], ...
            'URL',[], ...
            'ImplementInd',[], ...
            'VerifyInd',[], ...
            'FullID',[]),...
        'ImplementLink', struct(...
            'RequirementIdx',[], ...
            'ModelItemIdx',[]),...
        'ModelItem', struct(...
            'SID',[], ...
            'ImplementedInd',[]),...
        'VerifyLink', struct(...
            'RequirementIdx',[], ...
            'TestIdx',[]),...
        'Test', struct(...
            'Label',[], ...
            'VerifyInd',[], ...
            'SimulationInd',[], ...
            'URL',[]),...
        'Simulation', struct(...
            'RunId',[], ...
            'TestIdx',[], ...
            'URL',[], ...
            'Label',[]),...
        'modelItemMap', struct(...
            'Keys',[],...
            'Values',[]));
    
    reqInfo_NoMaps = flattenMaps(this.reqInfo);
    reqInfoOut = scopeToTemplate(reqInfoTemplate, reqInfo_NoMaps);
end

function sOut = flattenMaps(sIn)
% "Flatten" out any Map data structures found in the struct.

    sOut = sIn;
    fields = fieldnames(sIn);
    for i = 1:length(fields)
        cur = sIn.(fields{i});
        if isa(cur, 'containers.Map')
            sOut.(fields{i}) = struct('Keys', cur.keys, 'Values', cur.values);
        end
    end
end

function sOut = scopeToTemplate(sTemplate, sIn)
% Assign sIn to sOut, only keeping the fields found in sTemplate.

    % Remove extra top level fields
    sOut = removeExtraFields(sTemplate, sIn);
    
    % Remove extra sub-fields.
    topFields = fieldnames(sTemplate);
    for i = 1:length(topFields)
        f = topFields{i};
        sOut.(f) = removeExtraFields(sTemplate.(f), sIn.(f));
    end
end

function sOut = removeExtraFields(sTemplate, sIn)
% Remove any fields of sIn that aren't in sTemplate
    fields_Expected = fieldnames(sTemplate);
    fields_Actual = fieldnames(sIn);
    rmIdx = ~ismember(fields_Actual, fields_Expected);
    fieldsToRemove = fields_Actual(rmIdx);
    sOut = rmfield(sIn, fieldsToRemove);
    if isempty(sOut)
        sOut = [];
    end
end