function hValidateAttributes( varargin )
%hValidateAttributes  validate attributes of a codistributed array
%   
%   hValidateAttributes(A,CLASSES,ATTRIBUTES)
%   hValidateAttributes(A,CLASSES,ATTRIBUTES,ARGINDEX)
%   hValidateAttributes(A,CLASSES,ATTRIBUTES,FUNCNAME)
%   hValidateAttributes(A,CLASSES,ATTRIBUTES,FUNCNAME,VARNAME)
%   hValidateAttributes(A,CLASSES,ATTRIBUTES,FUNCNAME,VARNAME,ARGINDEX)
%   
%   Example:
%   spmd
%       A = codistributed([ 1 2 3; 4 5 6 ]);
%       B = codistributed([ 7 8 9; 10 11 12]);
%       C = cat(3, A, B);
%       hValidateAttributes(C,{'numeric'},{'2d'},'my_func','my_var',2)
%   end
%   
%   See also: validateattributes

%   Copyright 2014-2023 The MathWorks, Inc.

narginchk(3,6);

% Logic copied from matlab.internal.validators.attributes
try
    [ A, classes, attrs, fname, msgId, argname, argpos ] = checkInputs( varargin );
catch e
    % only VALIDATEATTRIBUTES should be on the stack
    throw(e)
end

% check the class of A
checkClass( A, classes, fname, msgId, argname, argpos );

% Pass down to the normal validator, ignoring the class. Note that the
% internal function cannot deal with string arrays, so convert to cellstr.
classes = {class(A)};
if isstring(attrs)
    attrs = cellstr(attrs);
end
matlab.internal.validators.attributes(A,classes,attrs,fname,argname,argpos);

end % hValidateAttributes



function checkClass( A, classes, fname, msgId, argname, argpos )
% Deal with the class argument.

if ismember("numeric", classes) && isnumeric(A)
    % OK
    return
end

clz = underlyingType(A);
if ~ismember(clz, classes)
    classesStr = sprintf( '%s, ', classes{:} );
    if ~isempty( classesStr )
        classesStr(end-1:end) = [];
    end
    
    argDes = matlab.internal.validators.getArgumentDescriptor( msgId, argname, argpos );
    error( matlab.internal.validators.generateId( fname, 'invalidType' ), '%s', ...
        getString(message( 'MATLAB:validateattributes:invalidType', ...
        argDes, classesStr, underlyingType(A) )));
end
end % checkClass



function [ A, classes, attrs, fname, msgId, argname, argpos ]  = checkInputs( inputs )

A = inputs{1};
classes = inputs{2};
attrs = inputs{3};

if ~(isstring( classes ) || iscellstr( classes ) || ischar( classes ))
    error(message('MATLAB:validateattributes:badClassList'))
end

if ~(isstring( attrs ) || iscell( attrs ))
    error( message('MATLAB:validateattributes:badAttributeList') )
end

[ fname, msgId, argname, argpos ] = matlab.internal.validators.generateArgumentDescriptor( ...
    inputs(4:end), 'validateattributes' );

end % checkInputs
