function [X,included,range,notfound,list] = ...
    db2array(d,list,range,shift,loglin, ...
    thrownotfound,throwinvalid,throwfreq,thrownontseries)
% db2array  Convert tseries database entries to numeric array.
%
% Syntax
% =======
%
%     [X,included,range] = db2array(d,list,range)
%
% Input arguments
% ================
%
% * `d` [ struct ] - Input database with tseries objects that will be
% converted to a numeric array.
%
% * `list` [ char | cellstr ] - List of tseries names that will be
% converted to a numeric array.
%
% * `range` [ numeric | Inf ] - Date range.
%
% Output arguments
% =================
%
% * `X` [ numeric ] - Numeric array with observations from individual
% tseries objects in columns.
%
% * `included` [ cellstr ] - List of tseries names that have been actually
% found in the database.
%
% * `range` [ numeric ] - Date range actually used.
%
% Description
% ============
%
% Example
% ========
%

% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

if nargin < 2
    list = fieldnames(d);
elseif ischar(list)
    list = regexp(list,'\w+','match');
end
list = list(:).';

if nargin < 3
    range = Inf;
end

if nargin < 4
    shift = zeros(size(list));
end

if nargin < 5
    loglin = false(size(list));
end

if nargin < 6
    thrownotfound = true;
end

if nargin < 7
    throwinvalid = true;
end

if nargin < 8
    throwfreq = true;
end

if nargin < 9
    thrownontseries = true;
end

if isnumeric(list) && (iscellstr(range) || ischar(range))
    [list,range] = deal(range,list);
end

if ischar(list)
    list = regexp(list,'\w+','match');
end

%**************************************************************************

if any(isinf(range([1,end])))
    range2 = dbrange(d,list);
end

if isinf(range(1))
    startdate = range2(1);
else
    startdate = range(1);
end

if isinf(range(end))
    enddate = range2(end);
else
    enddate = range(end);
end

nlist = length(list);
range = startdate : enddate;
rangefreq = datfreq(startdate);
nper = numel(range);
notfound = false(1,nlist);
invalid = false(1,nlist);
included = false(1,nlist);
freqmismatch = false(1,nlist);
nontseries = false(1,nlist);
X = [];
for i = 1 : nlist
    if isfield(d,list{i})
        if ~istseries(d.(list{i}))
            nontseries(i) = true;
            continue
        end
        tmpfreq = freq(d.(list{i}));
        if ~isnan(tmpfreq) && rangefreq ~= tmpfreq
            ndata = max(1,size(X,3));
            Xi = nan(nper,ndata);
            freqmismatch(i) = true;
        else
            Xi = rangedata(d.(list{i}),range+shift(i));
        end
        if isempty(X)
            X = nan(nper,nlist,size(Xi,2));
        end
        naltx = size(X,3);
        naltxi = size(Xi,2);
        % If needed, expand number of alternatives
        % in current array or current addition.
        if naltx == 1 && naltxi > 1
            X = X(:,:,ones(1,naltxi));
            naltx = naltxi;
        elseif naltx > 1 && naltxi == 1
            Xi = Xi(:,ones(1,naltx));
            naltxi = naltx;
        end
        if naltx == naltxi
            if loglin(i)
                Xi = log(Xi);
            end
            X(:,i,1:naltxi) = Xi; %#ok<AGROW>
            included(i) = true;
        else
            invalid(i) = true;
        end
    else
        notfound(i) = true;
    end
end

included = list(included);

if thrownotfound && any(notfound)
    warning('iris:data', ...
        '\n*** This database entry does not exist or is not a tseries object: ''%s''.', ...
        list{notfound});
end

if throwinvalid && any(invalid)
    warning('iris:data', ...
        '\n*** This database entry does not match the size of others: ''%s''.', ...
        list{invalid});
end

if throwfreq && any(freqmismatch)
    warning('iris:data', ...
        '\n*** This database entry does not match the frequency of the dates requested: ''%s''.', ...
        list{freqmismatch});
end

if thrownontseries && any(nontseries)
    warning('iris:data', ...
        '\n*** This variable or shock is in the database, but is not a tseries object: ''%s''.', ...
        list{nontseries});
end

if isempty(X)
    X = nan(nper,nlist);
end

end
