function this = set(this,varargin)
% set  Set modifiable model object properties.
%
% Syntax
% =======
%
%     m = set(m,name,value)
%     m = set(m,name,value,name,value,...)
%
% Input arguments
% ================
%
% * `m` [ model ] - Model object.
%
% * `name` [ char ] - Name of a modifiable model property that will be
% changed.
%
% * `value` [ ... ] - Value to which the property will be set.
%
% Output arguments
% =================
%
% * `m` [ model ] - Model object with the requested property modified.
%
% Modifiable properties
% ======================
%
% Labels
% --------
%
% * `'yLabels='` [ cellstr ] - Labels added to measurement equations.
%
% * `'xLabels='` [ cellstr ] - Labels added to transition equations.
%
% * `'dLabels='` [ cellstr ] - Labels added to deterministic-trend
% equations.
%
% * `'lLabels='` [ cellstr ] - Labels added to dynamic links.
%
% Annotations
% -------------
%
% * `'yAnnotations='` [ cellstr ] - Annotations added to measurement
% equations.
%
% * `'xAnnotations='` [ cellstr ] - Annotations added to transition
% equations.
%
% * `'eAnnotations='` [ cellstr ] - Annotations added to shocks.
%
% * `'pAnnotations='` [ cellstr ] - Annotations added to parameters.
%
% Miscellaneous
% ---------------
%
% * `'nAlt='` [ numeric ] - Number of alternative parameterisations.
%
% * `'stdVec='` [ numeric ] - Vector of std deviations.
%
% * `'tOrigin='` [ numeric ] - Base year for deterministic time trends in
% measurement variables.
%
% * `'epsilon='` [ numeric ] - Relative differentiation step when computing
% Taylor expansion.
%

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

P = inputParser();
P.addRequired('m',@ismodel);
P.addRequired('name',@iscellstr);
P.addRequired('value',@(x) length(x) == length(varargin(1:2:end-1)));
P.parse(this,varargin(1:2:end-1),varargin(2:2:end));

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

varargin(1:2:end-1) = strtrim(varargin(1:2:end-1));
n = length(varargin);
found = true([1,n]);
validated = true([1,n]);
for iarg = 1 : 2 : n
    [found(iarg),validated(iarg)] = ...
        doset(lower(varargin{iarg}),varargin{iarg+1});
end

% Report queries that are not modifiable model object properties.
if any(~found)
    utils.error('model', ...
        'This is not a modifiable model object property: ''%s''.', ...
        varargin{~found});
end

% Report values that do not pass validation.
if any(~validated)
    utils.error('model', ...
        'The value for this property does not pass validation: ''%s''.', ...
        varargin{~validated});
end


%**************************************************************************
    function [found,validated] = doset(usrquery,value)
        
        found = true;
        validated = true;
        query = model.myalias(usrquery);
        
        switch query
            
            case 'nalt'
                if isnumericscalar(value) ...
                        && value > 0 && value == round(value)
                    this = alter(this,value);
                else
                    validated = false;
                end
                
            case 'stdvec'
                ne = length(this.solutionid{3});
                nalt = size(this.Assign,3);
                if isnumeric(value) && ...
                        (numel(value) == ne || numel(value) == ne*nalt)
                    if numel(value) == ne
                        value = value(:).';
                        value = value(1,:,ones([1,nalt]));
                    elseif size(value,3) == 1
                        value = permute(value,[3,1,2]);
                    end
                    this.Assign(1,1:ne,:) = value;
                else
                    validated = false;
                end
                
            case 'torigin'
                if isnumericscalar(value) && value == round(value)
                    this.torigin = value;
                else
                    validated = false;
                end
                
            case 'userdata'
                this = userdata(this,value);
                
            case 'epsilon'
                if isnumericscalar(value) && value > 0
                    this.epsilon = value;
                else
                    validated = false;
                end
                
            case 'label'
                empty = cellfun(@isempty,this.eqtn);
                if iscell(value) && length(value) == 4 ...
                        && all(cellfun(@iscellstr,value)) ...
                        && length(value{1}) == sum(this.eqtntype == 1) ...
                        && length(value{2}) == sum(this.eqtntype == 2) ...
                        && length(value{3}) == sum(this.eqtntype == 3 & ~empty) ...
                        && length(value{4}) == sum(this.eqtntype == 4 & ~empty)
                    this.eqtnlabel(this.eqtntype == 1) = value{1};
                    this.eqtnlabel(this.eqtntype == 2) = value{2};
                    this.eqtnlabel(this.eqtntype == 3 & ~empty) = value{3};
                    this.eqtnlabel(this.eqtntype == 4 & ~empty) = value{4};
                else
                    validated = false;
                end
                
            case {'ylabel','xlabel','dlabel','llabel'}
                empty = cellfun(@isempty,this.eqtn);
                index = this.eqtntype == find(query(1) == 'yxdl') & ~empty;
                if iscellstr(value) && length(value) == sum(index)
                    this.eqtnlabel(index) = value;
                else
                    validated = false;
                end
                
            case 'rlabel'
                if iscellstr(value) ...
                        && length(value) == length(this.outside.label)
                    this.outside.label = value;
                else
                    validated = false;
                end
                
            case 'annotation'
                if isstruct(value)
                    for i = 1 : length(this.name)
                        if isfield(value,this.name{i}) && ischar(value.(this.name{i}))
                            this.namelabel{i} = value.(this.name{i});
                        end
                    end
                else
                    validated = false;
                end
                
            case {'yannotation','xannotation','eannotation','pannotation'}
                index = this.nametype == find(query(1) == 'yxep');
                if iscellstr(value) && length(value) == sum(index)
                    this.namelabel(index) = value;
                else
                    validated = false;
                end
                
            otherwise
                found = false;
                
        end
        
    end
% doset().

end