classdef AccessDependentDiagnostic < handle
%AccessDependentDiagnostic is a wrapper for MSLException/MSLDiagnostic.
%It allows to dynamically create diagnostics with/without fixit actions.
%
% This is an undocumented class. Its methods and properties are likely to
% change without warning from one release to the next.

% Copyright 2019-2020 The MathWorks, Inc.

properties (Access = 'private')
ErrorID;
ReadOnlyActionIDs;
FullAccessActionIDs;
Args;
end

properties
Causes {};
end

methods
function this = AccessDependentDiagnostic(aErrorID, aReadOnlyActionIDs, aFullAccessActionIDs, varargin)
this.ErrorID = aErrorID;
this.ReadOnlyActionIDs = this.getActionArg(aReadOnlyActionIDs);
this.FullAccessActionIDs = this.getActionArg(aFullAccessActionIDs);
this.Args = varargin;
end

function throw(this, isReadOnly)
% throw an MSLException
exception = this.getException(isReadOnly);
exception = this.addAllCauses(exception);
exception.throwAsCaller;
end

function reportWarning(this, isReadOnly)
% report an MSLDiagnostic
diagnostic = this.getDiagnostic(isReadOnly);
diagnostic = this.addAllCauses(diagnostic);
diagnostic.reportAsWarning;
end
end

methods (Access = 'private')

function msg = getMessage(this, isReadOnly)
if isReadOnly
actionIDs = this.ReadOnlyActionIDs;
else
actionIDs = [this.FullAccessActionIDs, this.ReadOnlyActionIDs];
end
% join the actionIDs into one argument
actionArg = strjoin(actionIDs, ', ');
% create message and diagnostic
msg = message(this.ErrorID, actionArg, this.Args{:});
end

function diagnostic = getDiagnostic(this, isReadOnly)
% create diagnostic
msg = this.getMessage(isReadOnly);
diagnostic = MSLDiagnostic(msg);
end

function exception = getException(this, isReadOnly)
% create exception
msg = this.getMessage(isReadOnly);
exception = MSLException(msg);
end

function action = getActionArg(~, argument)
if isempty(argument)
action = {'NO_ACTION'};
else
action = argument;
end
end

function diagnostic = addAllCauses(this, diagnostic)
% add diagnostic causes
for i = 1:numel(this.Causes)
diagnostic = diagnostic.addCause(this.Causes{i});
end
end
end
end