
%

%   Copyright 2013-2020 The MathWorks, Inc.

classdef AbstractTransform < matlab.mixin.Heterogeneous & handle
% Abstract transform defines the transform interface
%
% A transform must implement three methods
%
% - applicable: Determine from the block handle whether the rule
%   should be consulted
%
% - analyze: Analyze the block and provide useful information
%   for the global dataflow analysis
%
% - transform: Modify the model in-place
%
% - transformCopy: Perform the transform on the model copy

    properties (Abstract)
        pivotBlockType
        redundant
    end
    methods(Access=public, Abstract)

        % Whether the transformation rule is applicable
        yesno = applicable(obj, bh, cvd)

        % Analyze a given model to determine inactive parts
        % Return the inactive block handle and input port handles,
        % Also return the handles to subsystems that have active
        % execution logic, if any.
        [inactiveBlkHandle, inactiveInputPortHandles, exeContextHandles] = ...
            analyze(obj, bh, mdl, cvd, mdlStructureInfo);
        % NOTE analyze saves the intermediate result of this rule in the
        % analysisResults field

        % Use the saved analysis results to transform the model
        transform(obj, sliceXfrmr, mdl);

        % Transform the copy of the model
        transformCopy(obj, sliceXfrmr, refMdlToMdl, mdl, mdlCopy, atomicGroups);


    end

    methods (Access = public)
        function keeps = filterDeadBlocks(obj, handles)
        % Nothing
            keeps = [];
        end

        function reset(obj)
        % Clear the cache
        % During analysis the transform may saves block handles to be
        % removed.
        end

        function filterBlocksInAtomicGroup(obj,atomicGroups,opts)
            if isprop(obj,'redundant') && ~isempty(obj.redundant)
                bh = [obj.redundant.handle];
                delIdx = [];
                for i=1:length(bh)
                    if ~opts.InlineOptions.ModelBlocks ...
                            && bdroot(bh(i)) ~= atomicGroups.mdlH
                        delIdx(end+1) = i; %#ok<AGROW>
                    elseif atomicGroups.toParent.isKey(bh(i))
                        delIdx(end+1) = i; %#ok<AGROW>
                    end
                end
                obj.redundant(delIdx) = [];
            end
        end
    end

end
