classdef CodeCoverageSettings
%CODECOVERAGESETTINGS allows configuration of code coverage settings

%   Copyright 2010-2017 The MathWorks, Inc.

    properties (SetAccess=public, GetAccess=public)
        TopModelCoverage;
        ReferencedModelCoverage;
        CoverageTool;
    end

    methods (Access=public, Static=true)

        function updatedBuildHooks = updateBuildHooksWrapper(covSettings, oldBuildHooks)
        % Wrapper to do error checking before invoking the apply method
            if isempty(covSettings) || ...
                    ~isa(covSettings,'coder.coverage.CodeCoverageSettings')
                DAStudio.error('CoderCoverage:AllTools:invalidSettings');
            else
                updatedBuildHooks = coder.coverage.updateBuildHooks(covSettings, oldBuildHooks);
            end
        end

    end


    methods (Access=private, Static=true)

        function str = cellToCommaSeparatedStr(cellArray)
            ca = strcat(cellArray,''',');
            ca = strcat('''', ca);
            str = strcat(ca{:});
            str = regexprep(str,'\s*'',',''', ');
            str = str(1:end-2);
        end


        function fullValue = validateSetting(value, allowedValues)
            validSetting = false;
            if ischar(value)
                idx = strcmp(allowedValues, value);
                if sum(idx)==1
                    fullValue=allowedValues{idx};
                    validSetting=true;
                end
            end
            if ~validSetting
                allowedValuesStr=coder.coverage.CodeCoverageSettings.cellToCommaSeparatedStr...
                    (allowedValues);
                DAStudio.error('CoderCoverage:AllTools:InvalidCoverageSetting',...
                               value, allowedValuesStr);
            end
        end


    end

    methods

        function this = set.TopModelCoverage(this,value)

            % support string input
            value = convertStringsToChars(value);

            allowedValues = {'on','off'};
            this.TopModelCoverage=coder.coverage.CodeCoverageSettings.validateSetting...
                (value,allowedValues);
        end

        function this = set.ReferencedModelCoverage(this,value)

            % support string input
            value = convertStringsToChars(value);

            allowedValues = {'on','off'};
            this.ReferencedModelCoverage=coder.coverage.CodeCoverageSettings.validateSetting...
                (value,allowedValues);
        end

        function this = set.CoverageTool(this,value)

            % support string input
            value = convertStringsToChars(value);

            toolNames = coder.coverage.CodeCoverageHelper.getTools();

            % If the customization manager is not yet initialized, we
            % cannot retrieve the available tools. In that case, we skip
            % the validation.
            if ~isempty(toolNames)
                this.CoverageTool=coder.coverage.CodeCoverageSettings.validateSetting...
                    (value,toolNames);
            else
                this.CoverageTool=value;
            end
        end

    end

    methods (Access=public)

        function this = CodeCoverageSettings(lRTWBuildHooks, varargin)

            % Default values
            coverageTool = 'None';
            topModel='off';
            refModels='off';

            if ~isempty(lRTWBuildHooks)

                [toolNames, toolClasses] = coder.coverage.CodeCoverageHelper.getTools();

                hooks = cell(size(toolClasses));
                covToolEnabled = false(size(hooks));

                for i=1:length(hooks)
                    hook = coder.coverage.BuildHook.getBuildHookFromHooksForClass...
                           (lRTWBuildHooks, toolClasses{i});
                    if ~isempty(hook) && strcmp(hook.enabled, 'on')
                        settings = ...
                            coder.coverage.CodeCoverageHelper.getCovSettingsFromHook(hook);
                        topModel = settings.TopModelCoverage;
                        refModels = settings.ReferencedModelCoverage;
                        covToolEnabled(i) = true;
                    end
                end

                % There must be no more than one coverage tool that is enabled
                if sum(covToolEnabled) == 0
                    % Use default setting (None) for code coverage tool
                elseif sum(covToolEnabled) == 1
                    coverageTool = toolNames{covToolEnabled};
                else
                    DAStudio.error('CoderCoverage:AllTools:InvalidBuildHook');
                end

            elseif nargin == 4  % create object from previously serialized object
                topModel = varargin{1};
                refModels = varargin{2};
                coverageTool = varargin{3};
            end

            this.TopModelCoverage = topModel;
            this.ReferencedModelCoverage = refModels;
            this.CoverageTool = coverageTool;

        end

        % method to return a MATLAB code that can rebuild the object.
        % used by configset.internal.util.toMScript
        function code = serialize(this)
            code = 'coder.coverage.CodeCoverageSettings([]';
            code = [code, ',''',this.TopModelCoverage,''''];
            code = [code, ',''',this.ReferencedModelCoverage,''''];
            code = [code, ',''',this.CoverageTool,''''];
            code = [code,')'];
        end
    end

end
