classdef MySignalMatFile < Simulink.io.FileType
% MySignalMatFile illustrates how to read and write to an application-specific MAT-file using the Simulink.io.FileType class and methods.
%   The application-specific MAT-file that MySignalMatFile reads contains the structure, 
%   'myDataStructForMyUI'. It has 2 fields, signalArray and signalNames. 
%   signalArray is a cell array containing timeseries signals. signalNames is 
%   a cellstr where each element contains the name of the corresponding signal in 
%   signalArray, identified with the corresponding element index.


%   Copyright 2019-2020 The MathWorks, Inc.
    
    %======================================================================
    methods ( Static )
        
        %------------------------------------------------------------------
        function isSupported = isFileSupported( fileLocation )
            isSupported = false;
                        
            [ ~, ~, ext ] = fileparts( fileLocation );
            
            %If the extension is a MAT-file.
            if strcmpi(ext, '.mat')
                isSupported = true;
            end
        end
        
        %------------------------------------------------------------------
        function aFileReaderDescription = getFileTypeDescription( )
            aFileReaderDescription = 'An application specific MAT-file type.';
        end
        
    end
    
    %======================================================================
    methods 
        
        %------------------------------------------------------------------
        function validateFileNameImpl( aFile, filename ) %#ok<INUSL>
            %validateFileNameImpl
            isSupported = Simulink.io.MySignalMatFile.isFileSupported( filename );
            
            if ~isSupported
                error('This file format is not supported by my application.');
            end
        end
        
        %------------------------------------------------------------------
        function aList = whosImpl( aFile )
            aList = [];
            checkList = whos ('-file' , aFile.FileName );
            if isempty( checkList ) || ~any( strcmp( {checkList(:).name},'myDataStructForMyUI' ) )
                
                return;
            end
            %Implement the whosImpl method to determine the contents of the
            %MAT-file.
            data = load(aFile.FileName, 'myDataStructForMyUI');
            myDataStructForMyUI = data.myDataStructForMyUI;
            
            aList = struct;
            
            %For each name.
            for kName = 1: length( myDataStructForMyUI.signalNames )
                
                aList( kName ).name = ...
                    myDataStructForMyUI.signalNames{ kName };
                
                %Optional return type. See documentation for supported types names.
                aList( kName ).type = 'Signal';
            end
        end
        
        %------------------------------------------------------------------
        function varOut = loadAVariableImpl( aFile, varName )
            
            varOut = struct;
            
            data = load(aFile.FileName, 'myDataStructForMyUI');
            myDataStructForMyUI = data.myDataStructForMyUI;
            
            isTheVarName = strcmp( myDataStructForMyUI.signalNames, varName );
            
            if any( isTheVarName )
                varOut.(myDataStructForMyUI.signalNames{ isTheVarName }) = ...
                    myDataStructForMyUI.signalArray{ isTheVarName };
            else
                error([varName ' is not on file.']);
            end
            
        end
        
        %------------------------------------------------------------------
        function varOut = loadImpl( aFile )
            varOut = struct;
            
            data = load(aFile.FileName, 'myDataStructForMyUI');
            myDataStructForMyUI = data.myDataStructForMyUI;
            
            for k = 1: length( myDataStructForMyUI.signalNames )
                varOut.(myDataStructForMyUI.signalNames{ k }) = ...
                    myDataStructForMyUI.signalArray{ k };
            end
        end
        
        %------------------------------------------------------------------
        function [didWrite, errMsg] = exportImpl( aFile, fileName, cellOfVarNames, ...
                cellOfVarValues, isAppend)
            didWrite = false; %#ok<NASGU>
            errMsg = '';
            
            %If overwrite or create.
            if ~isAppend || ~exist( fileName, 'file')
                myDataStructForMyUI = struct;
                myDataStructForMyUI.signalNames = cellOfVarNames;
                myDataStructForMyUI.signalArray = cellOfVarValues;
            else
                %Otherwise, load the data.
                data = load( fileName, 'myDataStructForMyUI');
                
                if isfield( data, 'myDataStructForMyUI' )
                    myDataStructForMyUI = data.myDataStructForMyUI;
                    
                    myDataStructForMyUI.signalNames = ...
                        [ myDataStructForMyUI.signalNames cellOfVarNames];
                    myDataStructForMyUI.signalArray = ...
                        [ myDataStructForMyUI.signalArray cellOfVarValues];
                else
                    myDataStructForMyUI.signalNames = cellOfVarNames;
                    myDataStructForMyUI.signalArray = cellOfVarValues;
                end
                
                
            end
            
            saveStruct.myDataStructForMyUI = myDataStructForMyUI;
            
            try
                save( fileName, '-struct', 'saveStruct');
                didWrite = true;
            catch ME
                
                %Optional, return errMsg or throw hard error.
                % Returning an error message allows your automated
                % processes to carry on while allowing you to report the
                % error at a later time.
                errMsg = ME.message;
                didWrite = false;
            end
            
            
            
        end
    end
    
end
