% PARAM Parameter object class constructor.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: PARAM Parameter object class constructor.
%              Create a parameter object.
%
% SUPERCLASSES: ltpda_nuo < ltpda_obj
%
% CONSTRUCTORS:
%
%       p = param();                - creates an empty parameter
%       p = param(pl)               - creates a parameter from a
%                                     parameter list with the parameters:
%                                   - 'key' and 'val', or
%       p = param('key', val)       - creates a key/value pair
%                                     'val' can be from any type
%       p = param({key, desc}, val) - creates a key/value pair and a
%                                     description for the key
%       p = param('key', val, desc) - creates a key/value pair and a
%                                     description for the key
%
% VERSION:  $Id: param.m,v 1.72 2011/03/28 17:02:28 ingo Exp $
%
% SEE ALSO: ltpda_obj, ltpda_nuo, plist
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

classdef (Sealed = true, Hidden = true) param < ltpda_nuo
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                            Property definition                            %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  %---------- Public (read/write) Properties  ----------
  properties
  end
  
  %---------- Protected read-only Properties ----------
  properties (SetAccess = protected)
    key     = '';   % key of the key/value pair
    val     = [];   % value of the key/value pair
    desc    = '';   % description of the key/value pair
  end
  
  %---------- Protected Properties ----------
  properties (SetAccess = protected)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                          Check property setting                           %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    function set.key(obj, val)
      if ischar(val)
        obj.key = upper(val);
      else
        error('### The value for the property ''key'' must be a string\n### but it is from the class %s', class(val));
      end
    end
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                Constructor                                %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    function obj = param(varargin)
      
      switch nargin
        case 0
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%   no input   %%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          
          % Do nothing
          
        case 1
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%   one input   %%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          
          if isa(varargin{1}, 'param')
            %%%%%%%%%%  obj = param(param)   %%%%%%%%%%
            obj = copy(varargin{1}, 1);
            
          elseif isa(varargin{1}, 'plist')
            %%%%%%%%%%  obj = param(plist)   %%%%%%%%%%
            
            if nparams(varargin{1}) == 0
              %%%%%%%%%%  obj = param(plist())   %%%%%%%%%%
              %%%%%%%%%%  obj = param(plist('KEY', 'a', 'VAL', 1))   %%%%%%%%%%
              %%% is the plist is empty then return an empty param object
              
            else
              pl = varargin{1};
              pl_key  = find(pl, 'key');
              pl_val  = find(pl, 'val');
              pl_desc = find(pl, 'desc');
              if isempty(pl_key)
                error('### building a parameter from a plist requires one parameter in the plist is called ''key''');
              end
              if isempty(pl_val)
                error('### building a parameter from a plist requires one parameter in the plist is called ''val''');
              end
              
              obj.key  = pl_key;
              obj.val  = pl_val;
              if ~isempty(pl_desc)
                if ~ischar(pl_desc)
                  error('### The description of a parameter must be a string but it is from the class [%s]', class(pl_desc));
                end
                obj.desc = pl_desc;
              end
            end
            
          elseif isstruct(varargin{1})
            %%%%%%%%%%  obj = param(struct)   %%%%%%%%%%
            obj = fromStruct(obj, varargin{1});
            
          else
            error('### unknown constructor type for param object.');
          end
          
        case 2
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%   two inputs   %%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          if iscell(varargin{1})
            %%%%%%%%%%  obj = param({'key', 'desc'}, ...)   %%%%%%%%%%
            obj.key = varargin{1}{1};
            if ischar(varargin{1}{2});
              obj.desc = varargin{1}{2};
            else
              error('### The description of a parameter must be a string but it is from the class [%s]', class(varargin{1}{2}));
            end
            
          elseif isa(varargin{1}, 'org.apache.xerces.dom.DeferredElementImpl')
            %%%%%%%%%%   obj = param(DOM node, history-objects)   %%%%%%%%%%
            obj = fromDom(obj, varargin{1}, varargin{2});
            return
            
          else
            %%%%%%%%%%  obj = param('key', ...)   %%%%%%%%%%
            obj.key = varargin{1};
          end
          
          if  iscell(varargin{2})       && ...
              numel(varargin{2}) == 3   && ...
              isnumeric(varargin{2}{1}) && ...
              iscell(varargin{2}{2}) && ...
              isnumeric(varargin{2}{3})
            %%%%%%%%%%  obj = param(..., {idx2options, {options}, selectionMode})   %%%%%%%%%%
            %%%%%%%%%%  example: param(..., {1, {1 2 3}, 0})   %%%%%%%%%%
            %%%%%%%%%%  example: param(..., {1, {'a' 'b' 'c'}, 0})   %%%%%%%%%%
            obj.val = paramValue(varargin{2}{1}, varargin{2}{2}, varargin{2}{3});
            
          else
            obj.val = varargin{2};
          end
          
        case 3
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%   three inputs   %%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          obj.key  = varargin{1};
          obj.val  = varargin{2};
          if ischar(varargin{3})
            obj.desc = varargin{3};
          else
            error('### The description of a parameter must be a string but it is from the class [%s]', class(varargin{1}{2}));
          end
          
        otherwise
          error('### Unknown number of arguments.');
      end
      
    end
  end
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                              Methods (public)                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    varargout = mux(varargin);
    varargout = string(varargin)
    
    %%% Define Abstract methods
    varargout = char(varargin)
    varargout = copy(varargin)
    varargout = display(varargin)
    
    varargout = setKey(varargin)
    varargout = setVal(varargin)
    varargout = setDesc(varargin)
    varargout = setKeyVal(varargin)
    
    varargout = getVal(varargin)
    varargout = getDefaultVal(varargin)
    varargout = getOptions(varargin)
    
    varargout = setProperty(varargin)
    varargout = getProperty(varargin)
    
    p = setDefaultOption(p, option)
    p = setDefaultIndex(p, index)
  end
  
  methods (Hidden = true)
    varargout = attachToDom(varargin)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                              Methods (protected)                          %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Access = protected)
    varargout = fromStruct(varargin)
    varargout = fromDom(varargin)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                              Methods (private)                            %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Access = private)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                          Methods (Static, Public)                         %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Static = true)
    
    function out = VEROUT()
      out = '$Id: param.m,v 1.72 2011/03/28 17:02:28 ingo Exp $';
    end
    
    function ii = getInfo(varargin)
      ii = utils.helper.generic_getInfo(varargin{:}, 'param');
    end
    
    function out = SETS()
      out = {'Default'};
    end
    
    function out = getDefaultPlist(set)
      switch lower(set)
        case 'default'
          out = plist();
        otherwise
          error('### Unknown set [%s]', set');
      end
    end
    
    function obj = initObjectWithSize(n,m)
      obj = param.newarray([n m]);
    end
    
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                          Methods (Static, Private)                        %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Static = true, Access = private)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                         Methods (static, hidden)                          %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Static = true, Hidden = true)
    varargout = loadobj(varargin)
    varargout = update_struct(varargin)
  end
  
end

