function varargout = repo_test_func(varargin)
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  % DESCRIPTION: REPO_TEST_FUNC Tests the submit and retrieve of LTPDA objs in
  % a LTPDA database, measuring the submit/retrieve time.
  %
  % CALL:        s =  repo_test_func(pl)
  %
  % INPUTS:      pl - parameter list(s)
  %
  % OUTPUTS:     s  - an array of plists containing the results of the test.
  %                   If the submission/retrieve is not performed, most of
  %                   the keys will be empty
  %              In detail, each plist will contain:
  %
  % OUTPUT PARAMETER LIST:
  % <key>             <description>
  % ret_time_xml     - time for retrieval of data from xml (s)
  % ret_time_bin     - time for retrieval of data from binary (s)
  %	sub_time         - time for submission (s)
  % t                - absolute time of test execution
  % test_ID          - test identifier, also repeated in saved file
  % status           - result of comparison between submitted and retrieved objs
  % OBJids           - submitted objs IDs assigned by database
  % cid              - submitted objs collection ID assigned by database
  % start_time       - beginning time of test execution
  % stop_time        - ending time of test execution
  % obj_filesize     - size on disk of the xml and binary versions of every object
  % sinfo            - a struct with infos about the connection
  %
  % INPUT PARAMETER LIST:
  % <key>            <default value>             <description>
  % 'RAND_N_OBJ'      false           produces a random number of objects
  %                                   at a time
  % 'N_OBJ'           1               produces N_OBJ objects at a time.
  %                                   Inserting <= 0 will produce random
  %                                   number of objects
  % 'RAND_OBJ_TYPE'   false           produces a random object from ltpda_uo class
  % 'OBJ_TYPE'        'ao'            defines the object(s) to produce
  %                                   If empty or 'RAND', it will pick at random within
  %                                   the ltpda_uo class
  % 'RAND_AO'             true        Picks at random the parameters for
  %                                   the AO(s) to produce and submit
  % 'AO_PARAMS'           plist       plist to build the AO(s)
  % 'RAND_PLIST'          true        Picks at random the parameters for
  %                                   the plist(s) to produce and submit
  % 'PLIST_PARAMS'         plist      plist to build the plist(s)
  % 'RAND_MFIR'            true       Picks at random the parameters for
  %                                   the mfir(s) to produce and submit
  % 'MFIR_PARAMS'         plist       plist to build the mfir(s)
  % 'RAND_MIIR'           true        Picks at random the parameters for
  %                                   the miir(s) to produce and submit
  % 'MIIR_PARAMS'         plist       plist to build the miir(s)
  % 'RAND_PZMODEL' true               Picks at random the parameters for
  %                                   the pzmodel(s) to produce and submit
  % 'PZMODEL_PARAMS'      plist       plist to build the pzmodel(s)
  % 'RAND_TIMESPAN'         true      Picks at random the parameters for
  %                                   the timespan object(s)
  % 'TIMESPAN_PARAMS'      plist      plist to build the timespan(s)
  % 'RAND_SSM'              true      Picks at random the parameters for
  %                                   the ssm(s)
  % 'SSM_PARAMS'           plist      plist to build the ssm(s)
  % 'RAND_PARFRAC'         true      Picks at random the parameters for
  %                                   the parfrac object(s)
  % 'PARFRAC_PARAMS'       plist      plist to build the parfrac(s)
  % 'RAND_RATIONAL'        true      Picks at random the parameters for
  %                                   the rational object(s)
  % 'RATIONAL_PARAMS'      plist     plist to build the rational(s)
  %
  % 'HOSTNAME'        '130.75.117.67' the repository host IP (for individual tests)
  % 'DBASE'           'ltpda_test'    the database name (for individual tests)
  % 'COLL_RETRIEVE'   false           retrieves via the submitted collection ID
  % 'SAVE_OBJS'       false           saves the produced objs
  % 'OBJ_FILENAME'    'submit_trial_obj'  filename to save the produced
  %                                   obj(s)
  % 'OBJ_FILEFORMAT'  'xml'           format for the filename to save the produced
  %                                   obj(s)
  % 'DIR'             '/Users/MH/exper_data/test/obj_creation'
  %                                   path to save the produced obj(s) into
  % 'SUBMIT'          false           actually performs the submit/retrieve test
  % 'CONN'            empty           a conn struct if the connection was
  %                                   already open (for group tests)
  % 'SAVE_RESULTS'    true            saves the individual test results
  % 'RESULTS_FILENAME' 'repo_test'    filename to save results in
  % 'OBJ_FILESIZE'    true            calculate sizes (in bytes) of all objects
  %
  % VERSION:     $Id: repo_test_func.m,v 1.6 2009/03/25 17:39:01 nicola Exp $
  %
  % HISTORY:     05-12-2008 M Hueller
  %                 Creation
  %
  % M-FILE INFO: Get information about this methods by calling
  %              >> ao.getInfo('repo_test_func')
  %
  %              Get information about a specified set-plist by calling:
  %              >> ao.getInfo('repo_test_func', 'None')
  %
  % SEE ALSO: run_UTN_repo_test
  %
  % SEE: <a href="matlab: help ao/Contents;">HELP: All Analysis Object Functions:</a>
  %      <a href="matlab: helpwin ao/Contents;">DOC: All Analysis Object Functions:</a>
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%   global obj_size_xml obj_size_bin
  
  %% Check if this is a call for parameters
  if utils.helper.isinfocall(varargin{:})
    varargout{1} = getInfo(varargin{3});
    return
  end
  
  % Collect input variable names
  in_names = cell(size(varargin));
  for ii = 1:nargin
    in_names{ii} = inputname(ii);
  end
  
  % Collect all plists
  pls = utils.helper.collect_objects(varargin(:), 'plist', in_names);
  
  %% ---------------- Produce one plist
  if isa(pls, 'plist')
    pls = combine(pls, getDefaultPlist());
  else
    pls = getDefaultPlist();
  end
  
  import utils.const.*;
  
  %% ---------------- Initial settings
  
  % Checks if running on PC
  if ispc
    path_symbol = '\';
  else
    path_symbol = '/';
  end
  
  % Verify if the user wants only to produce objects or also test repository
  if find(pls, 'SUBMIT')
    % Collects the conn struct.
    conn = find(pls, 'CONN');
    % If empty, goes ahead and looks for the repository IP and database, and
    % opens the connection
    if isempty(conn)
      
      % Get the hostname
      hostname = find(pls, 'HOSTNAME');
      
      % Get the database name
      database_name = find(pls, 'DBASE');
      
      % Opens the connection
      conn = utils.mysql.connect(hostname, database_name);
    end
  else
    utils.helper.msg(msg.MNAME, '%s\n%s', ...
      '  ','Submission switched off, only producing the objects ');
  end
  
  if ~find(pls, 'SAVE_OBJS')
    utils.helper.msg(msg.MNAME, '%s\n%s', ...
      '  ','Saving switched off, only displaying the objects ');
  end
    
  %% Builds the trial objects
  
  % Limiting the number of objects in the case of random number to
  % something reasonable
  N_MAX_OBJS = 100;
  
  % Limiting the number of poles and zeros in the case of random extraction to
  % something reasonable
  N_MAX_POLES = 100;
  N_MAX_ZEROS = 100;
  
  % Limitng the number of values for cdata and xydata to something
  % reasonable
  N_MAX_VALS = 1000;
  
  % Number of objects to be created
  N_OBJ = find(pls, 'N_OBJ');
  
  if N_OBJ < 1 || find(pls, 'RAND_N_OBJ')
    % Pick a random rumber between 1 and N_MAX_OBJS
    N_OBJ = utils.math.randelement(N_MAX_OBJS, 1);
  end
  
  % Finds the kind of objects requested by user
  user_class_list = utils.helper.ltpda_userclasses;
  
  obj_type = find(pls, 'OBJ_TYPE');
  rand_obj_type = true;
  % Go for random value in the case of:
  % invalid or empty class name, or explicitely asked random
  if ~isempty(obj_type) && ~strcmpi(obj_type, 'RAND') && ~find(pls, 'RAND_OBJ_TYPE')
     % Checks if user entered a user class name
    for kk = 1:length(user_class_list)
      if strcmpi(user_class_list{kk}, obj_type)
        rand_obj_type = false;
      end
    end
  end
  
  % Prepares the empty cell array for the object(s) and the plist(s)
  objs = cell(N_OBJ, 1);
  pl_objs = cell(N_OBJ, 1);
  
  % Main loop over the number of requested objects
  for kk = 1:N_OBJ
    if rand_obj_type
      % Picks up at random one user class name
      utils.helper.msg(msg.MNAME, '%s\n%s', ...
        '  ',['User input class ' upper(obj_type) ' not used, go for random class']);
      index = utils.math.randelement(length(user_class_list),1);
      obj_type = user_class_list{index};
    end
    
    % Test ID based on time elapsed since a reference time
    ref_time = time('2008-01-01 00:00:00');
    test_ID = floor(time - ref_time);
    
    % For the time being SSM are disabled:
    if strcmp(obj_type,'ssm'), obj_type = 'ao'; end
       
       
    switch obj_type
      case 'ao'
        ao_params = find(pls, 'AO_PARAMS');
        if isempty(ao_params) || ~ao_params.nparams || find(pls, 'RAND_AO');
          % The plist to build the object is built by picking at random from
          % a "menu" list, based on
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
          pl_obj = plist();
          p_menu = provide_menu('ao');
          
          % Extract at random a type of data
          dtype = lower(cell2mat(utils.math.randelement(find(p_menu, 'dtype'), 1)));
          p_menu_sub = find(p_menu, dtype);
          
          switch lower(dtype)
            case 'tsdata'
              pl_obj = plist(...
                'waveform', cell2mat(utils.math.randelement(find(p_menu_sub, 'waveform'), 1)), ...
                'fs', utils.math.randelement(find(p_menu_sub,'fs'), 1), ...
                'nsecs', utils.math.randelement(find(p_menu_sub,'nsecs'), 1), ...
                'name', cell2mat(utils.math.randelement(find(p_menu_sub,'name'), 1)), ...
                'yunits', unit(cell2mat(utils.math.randelement(find(p_menu_sub, 'yunits'), 1))) ...
                );
              switch find(pl_obj, 'waveform')
                case 'sine wave'
                  n_freqs = utils.math.randelement(3,1);
                  pl_obj.combine(pl_obj, plist(...
                    'A', utils.math.randelement(find(p_menu_sub,'A'), n_freqs), ...
                    'f', utils.math.randelement(find(p_menu_sub,'f'), n_freqs), ...
                    'phi', utils.math.randelement(find(p_menu_sub,'phi'), n_freqs), ...
                    'toff', utils.math.randelement(find(p_menu_sub,'toff'), n_freqs) ...
                    ));
                case 'noise'
                  pl_obj.combine(pl_obj, plist(...
                    'type', cell2mat(utils.math.randelement(find(p_menu_sub, 'type'), 1)), ...
                    'sigma', utils.math.randelement(find(p_menu_sub,'sigma'), 1) ...
                    ));
                case 'chirp'
                  pl_obj.combine(pl_obj, plist(...
                    'f0', utils.math.randelement(find(p_menu_sub,'f0'), 1), ...
                    'f1', utils.math.randelement(find(p_menu_sub,'f1'), 1), ...
                    't1', utils.math.randelement(find(p_menu_sub,'t1'), 1) ...
                    ));
                case 'gaussian pulse'
                  pl_obj.combine(pl_obj, plist(...
                    'f0', utils.math.randelement(find(p_menu_sub,'f0'), 1), ...
                    'bw', utils.math.randelement(find(p_menu_sub,'bw'), 1) ...
                    ));
                case 'square wave'
                  pl_obj.combine(pl_obj, plist(...
                    'f', utils.math.randelement(find(p_menu_sub,'f'), 1), ...
                    'duty', utils.math.randelement(find(p_menu_sub,'duty'), 1) ...
                    ));
                case 'sawtooth'
                  pl_obj.combine(pl_obj, plist(...
                    'f', utils.math.randelement(find(p_menu_sub,'f'), 1), ...
                    'width', utils.math.randelement(find(p_menu_sub,'width'), 1) ...
                    ));
                otherwise
                  
              end
              
            case 'fsdata'
              pl_obj = plist(...
                'fsfcn', cell2mat(utils.math.randelement(find(p_menu_sub, 'fsfcn'), 1)), ...
                'name', cell2mat(utils.math.randelement(find(p_menu_sub,'name'), 1)), ...
                'yunits', unit(cell2mat(utils.math.randelement(find(p_menu_sub, 'yunits'), 1))) ...
                );
              
              switch cell2mat(utils.math.randelement(find(p_menu_sub, 'f_mode'), 1))
                case 'build'
                  pl_obj.combine(pl_obj, plist(...
                    'f1', utils.math.randelement(find(p_menu_sub, 'f1'), 1), ...
                    'f2', utils.math.randelement(find(p_menu_sub, 'f2'), 1), ...
                    'nf', utils.math.randelement(find(p_menu_sub, 'nf'), 1), ...
                    'scale', cell2mat(utils.math.randelement(find(p_menu_sub, 'scale'), 1)) ...
                    ));
                case 'list'
                  f = find(p_menu_sub, 'f');
                  pl_obj.combine(pl_obj, plist(...
                    'f', logspace(f(1), f(2), 1e3)  ...
                    ));
                otherwise
                  
              end
              
            case 'cdata'
              vals = find(p_menu_sub,'vals');
              nvals = utils.math.randelement(N_MAX_VALS, 1);
              pl_obj = plist(...
                'vals', vals(1) + (vals(2) - vals(1))*rand(nvals, 1), ...
                'name', cell2mat(utils.math.randelement(find(p_menu_sub,'name'), 1)), ...
                'yunits', unit(cell2mat(utils.math.randelement(find(p_menu_sub, 'yunits'), 1))) ...
                );
              
            case 'xydata'
              xvals = find(p_menu_sub,'xvals');
              yvals = find(p_menu_sub,'yvals');
              nvals = utils.math.randelement(N_MAX_VALS, 1);
              pl_obj = plist(...
                'xvals', xvals(1) + (xvals(2) - xvals(1))*rand(nvals, 1), ...
                'yvals', yvals(1) + (yvals(2) - yvals(1))*rand(nvals, 1), ...
                'name', cell2mat(utils.math.randelement(find(p_menu_sub,'name'), 1)), ...
                'xunits', unit(cell2mat(utils.math.randelement(find(p_menu_sub, 'xunits'), 1))), ...
                'yunits', unit(cell2mat(utils.math.randelement(find(p_menu_sub, 'yunits'), 1))) ...
                );
              
            otherwise
              
          end
        else
          % The plist to build the object is the input plist
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from input plist']);
          pl_obj = ao_params;
        end
        
        % Builds the trial object, adding the test ID to the input plist
        obj = ao(pl_obj.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        
      case 'plist'
        plist_params = find(pls, 'PLIST_PARAMS');
        if isempty(plist_params) || ~plist_params.nparams || find(pls, 'RAND_PLIST');
          % The plist to build the object is built by picking at random from
          % a "menu" list, based on random 'key' and 'values' fields
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
          pl_obj = plist();
          p_menu = provide_menu('plist');
          n_params = utils.math.randelement(p_menu.nparams, 1);
          for jj = 1:n_params
            pl_obj.append(['Key' num2str(jj)], p_menu.params(utils.math.randelement(n_params, 1)).val)
          end
        else
          % The plist to build the object is the input plist
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from input plist']);
          pl_obj = plist_params;
        end
        
        % Builds the trial object, adding the test ID to the input plist
        obj = plist(pl_obj.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        % Saves some memory
        clear obj pl_obj;
        
      case 'mfir'
        mfir_params = find(pls, 'MFIR_PARAMS');
        if isempty(mfir_params) || ~mfir_params.nparams || find(pls, 'RAND_MFIR');
          % The plist to build the object is built by picking at random from
          % values in a "menu" list, based on the parameters 'From Standard Type'
          
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
          p_menu = provide_menu('mfir');
          
          pl_obj = plist(...
            'type', cell2mat(utils.math.randelement(find(p_menu, 'type'), 1)), ...
            'order', utils.math.randelement(find(p_menu, 'order'), 1), ...
            'gain', utils.math.randelement(find(p_menu, 'gain'), 1), ...
            'fs', utils.math.randelement(find(p_menu, 'fs'), 1), ...
            'fc', [1.0 1.2].*utils.math.randelement(find(p_menu, 'fc'), 1), ...
            'iunits', unit(cell2mat(utils.math.randelement(find(p_menu, 'iunits'), 1))), ...
            'ounits', unit(cell2mat(utils.math.randelement(find(p_menu, 'ounits'), 1))) ...
            );
        else
          % The plist to build the object is the input plist
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from input plist']);
          pl_obj = mfir_params;
        end
        
        % Builds the trial object, adding the test ID to the input plist
        obj = mfir(pl_obj.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        % Saves some memory
        clear obj pl_obj;
        
      case 'miir'
        miir_params = find(pls, 'MIIR_PARAMS');
        if isempty(miir_params) || ~miir_params.nparams || find(pls, 'RAND_MIIR');
          % The plist to build the object is built by picking at random from
          % values in a "menu" list, based on the parameters 'From Standard Type'
          
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
          p_menu = provide_menu('miir');
         
          pl_obj = plist(...
            'type', cell2mat(utils.math.randelement(find(p_menu, 'type'), 1)), ...
            'order', utils.math.randelement(find(p_menu, 'order'), 1), ...
            'gain', utils.math.randelement(find(p_menu, 'gain'), 1), ...
            'fs', utils.math.randelement(find(p_menu, 'fs'), 1), ...
            'fc', [1.0 1.2].*utils.math.randelement(find(p_menu, 'fc'), 1), ...
            'iunits', unit(cell2mat(utils.math.randelement(find(p_menu, 'iunits'), 1))), ...
            'ounits', unit(cell2mat(utils.math.randelement(find(p_menu, 'ounits'), 1))) ...
            );
        else
          % The plist to build the object is the input plist
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from input plist']);
          pl_obj = miir_params;
        end
        
        % Builds the trial object, adding the test ID to the input plist
        obj = miir(pl_obj.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        % Saves some memory
        clear obj pl_obj;
        
      case 'pzmodel'
        
        pzmodel_params = find(pls, 'pzmodel_PARAMS');
        if isempty(pzmodel_params) || ~pzmodel_params.nparams || find(pls, 'RAND_pzmodel');
          % The plist to build the object is built by picking at random from
          % values in a "menu" list, from the 'From Poles/Zeros'
          % constructor
          
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
          p_menu = provide_menu('pzmodel');
          
          v_poles = [];
          v_zeros = [];
          
          freq = find(p_menu, 'freq');
          Q = find(p_menu, 'Q');
          for jj = 1:utils.math.randelement(N_MAX_POLES, 1)
            v_poles = [v_poles pz(utils.math.randelement(freq, 1), utils.math.randelement(Q, 1))];
          end
          for jj = 1:utils.math.randelement(N_MAX_ZEROS, 1)
            v_zeros = [v_zeros pz(utils.math.randelement(freq, 1), utils.math.randelement(Q, 1))];
          end
          
          pl_obj = plist(...
            'gain', utils.math.randelement(find(p_menu, 'gain'), 1), ...
            'poles', v_poles, ...
            'zeros', v_zeros, ...
            'name', cell2mat(utils.math.randelement(find(p_menu, 'name'), 1)), ...
            'iunits', unit(cell2mat(utils.math.randelement(find(p_menu, 'iunits'), 1))), ...
            'ounits', unit(cell2mat(utils.math.randelement(find(p_menu, 'ounits'), 1))) ...
            );
        else
          % The plist to build the object is the input plist
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from input plist']);
          pl_obj = pzmodel_params;
        end
        
        % Builds the trial object, adding the test ID to the input plist
        obj = pzmodel(pl_obj.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        % Saves some memory
        clear obj pl_obj;
        
      case 'timespan'
        timespan_params = find(pls, 'TIMESPAN_PARAMS');
        if isempty(timespan_params) || ~timespan_params.nparams || find(pls, 'RAND_TIMESPAN');
          % The plist to build the object is built by picking at random from
          % values in a "menu" list, based on the parameters needed to
          % build it from definition
          
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
          p_menu = provide_menu('timespan');
          
          t = time;
          pl_obj = plist(...
            'startT', t.utc_epoch_milli, ...
            'endT', t.utc_epoch_milli + randi(t.utc_epoch_milli + 1e12, 1), ...
            'timezone', cell2mat(utils.math.randelement(find(p_menu, 'timezone'), 1)), ...
            'timeformat', cell2mat(utils.math.randelement(find(p_menu, 'timeformat'), 1)) ...
            );
        else
          % The plist to build the object is the input plist
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from input plist']);
          pl_obj = timespan_params;
        end
        
        % Builds the trial object, adding the test ID to the input plist
        obj = timespan(pl_obj.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        % Saves some memory
        clear obj pl_obj;
        
      case 'ssm'
        ssm_params = find(pls, 'SSM_PARAMS');
        if isempty(ssm_params) || ~ssm_params.nparams || find(pls, 'RAND_SSM');
          % The plist to build the object is built by picking at random from
          % values in a "menu" list, based on built-in models that can be
          % constructed without the Control System Toolbox
          
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
          p_menu = provide_menu('ssm');
          
          pl_obj = plist(...
            'built-in', cell2mat(utils.math.randelement(find(p_menu, 'model_list'), 1)) ...
            );
        else
          % The plist to build the object is the input plist
          utils.helper.msg(msg.MNAME, '%s\n%s', ...
            '  ',['Object from class ' upper(obj_type) ' built from input plist']);
          pl_obj = ssm_params;
        end
        
        % Builds the trial object, adding the test ID to the input plist
        obj = ssm(pl_obj.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        % Saves some memory
        clear obj pl_obj;
        
      case 'parfrac'
         parfrac_params = find(pls, 'PARFRAC_PARAMS');
         if isempty(parfrac_params) || ~parfrac_params.nparams || find(pls, 'RAND_PARFRAC');
            % The plist to build the object is built by picking at random from
            % values in a "menu" list, based on the parameters 'From Standard Type'
            utils.helper.msg(msg.MNAME, '%s\n%s', ...
               '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
            
            p_menu = provide_menu('parfrac');
            num_poles = utils.math.randelement([3:10],1);
            pl_obj = plist(...
               'res', utils.math.randelement(find(p_menu, 'res'), num_poles), ...
               'poles', utils.math.randelement(find(p_menu, 'poles'), num_poles), ... % this extracts num_poles pz objs from a vector of pz objs
               'dir', find(p_menu, 'dir'), ...
               'iunits', unit(cell2mat(utils.math.randelement(find(p_menu, 'iunits'), 1))), ...
               'ounits', unit(cell2mat(utils.math.randelement(find(p_menu, 'ounits'), 1))) ...
               );
         else
            % The plist to build the object is the input plist
            utils.helper.msg(msg.MNAME, '%s\n%s', ...
               '  ',['Object from class ' upper(obj_type) ' built from input plist']);
            pl_obj = parfrac_params;
         end
         obj = parfrac(pl_obj.append('test_ID', test_ID));
         
         % Adds the trial object to the cell array
         objs{kk} = obj;
         % Adds the plist for this object to the cell array
         pl_objs{kk} = pl_obj;
         % Saves some memory
         clear obj pl_obj;
        
      case 'rational'
         rational_params = find(pls, 'RATIONAL_PARAMS');
         if isempty(rational_params) || ~rational_params.nparams || find(pls, 'RAND_RATIONAL');
            % The plist to build the object is built by picking at random from
            % values in a "menu" list, based on the parameters 'From Standard Type'
            utils.helper.msg(msg.MNAME, '%s\n%s', ...
               '  ',['Object from class ' upper(obj_type) ' built from random parameters']);
            
            p_menu = provide_menu('rational');
            pl_obj = plist(...
               'num', utils.math.randelement(find(p_menu, 'num'), utils.math.randelement(10,1)), ...
               'den', utils.math.randelement(find(p_menu, 'den'), utils.math.randelement(10,1)), ...
               'iunits', unit(cell2mat(utils.math.randelement(find(p_menu, 'iunits'), 1))), ...
               'ounits', unit(cell2mat(utils.math.randelement(find(p_menu, 'ounits'), 1))) ...
               );
         else
            % The plist to build the object is the input plist
            utils.helper.msg(msg.MNAME, '%s\n%s', ...
               '  ',['Object from class ' upper(obj_type) ' built from input plist']);
            pl_obj = rational_params;
         end
         obj = rational(pl_obj.append('test_ID', test_ID));
         
         % Adds the trial object to the cell array
         objs{kk} = obj;
         % Adds the plist for this object to the cell array
         pl_objs{kk} = pl_obj;
         % Saves some memory
         clear obj pl_obj;        
      otherwise
        utils.helper.msg(msg.MNAME, '%s\n%s', ...
          '  ',['Object from class ' upper(obj_type) ' not available already, using AO instead']);
        
        % Go ahead with a simple tsdata AO
        p_menu = provide_menu('unsupported');
        obj = prepare_simple_ao(p_menu.append('test_ID', test_ID));
        
        % Adds the trial object to the cell array
        objs{kk} = obj;
        
        % Adds the plist for this object to the cell array
        pl_objs{kk} = pl_obj;
        
        % Saves some memory
        clear obj pl_obj;
    end
  end
  
  %% Saves on disk the data objects
  if find(pls,'save_objs')
    obj_save_path = find(pls, 'dir');
    obj_filename = find(pls, 'obj_filename');
    obj_fileformat = find(pls, 'obj_fileformat');
    
    for kk = 1:length(objs)
      obj = objs{kk};
      w = whos('obj');
      path_string = sprintf('%s%s%s_%s_%d_%04d.%s', ...
        obj_save_path, path_symbol, obj_filename ,...
        w.class, test_ID, kk, obj_fileformat);
      
      save(obj, path_string);
%       obj_size = dir(path_string);
%       if strcmpi(obj_fileformat,'xml')
%          obj_size_xml(kk) = obj_size.bytes;
%          obj_size_bin(kk) = zeros(size(objs));
%       else
%          obj_size_xml(kk) = zeros(size(objs));
%          obj_size_bin(kk) = obj_size.bytes;
%       end
    end
  else
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     %  To be updated with a proper new function to measure the filesize  %
     %                 when the objects are not saved                     %
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%      obj_size_xml = zeros(size(objs));
%      obj_size_bin = zeros(size(objs));
  end
  
  if find(pls, 'FILESIZE')
     clear objs_filesize
     objs_filesize{1,1} = 'XML';
     objs_filesize{1,2} = 'BIN';
     % The function must return the size (in bytes) of the objects generated
     for kk = 1:length(objs)
        obj = objs{kk};
        
        % Retrieve the XML filesize
        xml = com.mathworks.xml.XMLUtils.createDocument('obj');
        parent = xml.getDocumentElement;
        utils.helper.xmlwrite(obj, xml, parent, '');
        otxt = xmlwrite(xml);
        xml_size = whos('otxt');
        objs_filesize{kk+1,1} = xml_size.bytes;
        
        % Retrive the BIN filesize
        obj = utils.prog.rstruct(obj);
        bin_size = whos('obj');
        objs_filesize{kk+1,2} = bin_size.bytes;
        
        clear obj xml parent otxt xml_size bin_size
     end
  end

  
  
  %% Executes the submit/retrieve test
  if find(pls, 'SUBMIT')
    
    start_time = now;
    
    utils.helper.msg(msg.MNAME, '\n%s\n%s%d%s\n%s', ...
      '  ', '*===== Test ', test_ID, ' =========', '  ');
    
    % Submission and retrieval
    results = submitretrieve(conn, objs, test_ID, find(pls, 'coll_retrieve'));
    
    % Includes time for start and stop in serial form
    stop_time = now;
    results.append('start_time', datestr(start_time,'HH:MM:SS.FFF'), ...
      'stop_time', datestr(stop_time,'HH:MM:SS.FFF'));
    
  else
    results = plist;
  end
    
    
  %% Final report
  
  % Includes the plists for the creation of the objects
  results.append('pl_objs', pl_objs );
  
  % Includes the plist input by the user, combined with default
  results.append('pl_used', pls );
  
  if find(pls, 'FILESIZE')
     % Includes the size of the objects
     results.append('objs_filesize', objs_filesize);
  end
  
  
  if find(pls, 'save_results')    
    % Saves the test results
    save(...
      [find(pls, 'dir') path_symbol find(pls, 'results_filename') '_' num2str(test_ID) '.mat'], ...
      'results');
  end
  
  varargout{1} = results;
  
  
  %% Closes connection if stand-alone run
  if ~isempty(find(pls, 'conn'))
    % Close connection
    close(conn);
  end
end

%--------------------------------------------------------------------------
% Provides the "menu" lists where to pick from
%--------------------------------------------------------------------------
function out_list = provide_menu(obj)
  switch lower(obj)
    case 'ao'
      t = time;
      out_list = plist(...
        'dtype', {'tsdata', 'fsdata', 'cdata', 'xydata'}, ...
        'tsdata',   plist(...
        'waveform', {...
        'sine-wave', 'chirp', 'noise', 'Gaussian pulse', 'Square wave', 'Sawtooth'}, ...
        'fs', [0.1:0.1:10], ...
        'nsecs', logspace(1,6,1000), ...
        't0', t, ...
        'A', linspace(-10,10,1001), ...
        'f', logspace(-1,-4,100), ...
        'phi', linspace(-2*pi,2*pi,21), ...
        'toff', linspace(0,1e4,101), ...
        'type', {'Normal', 'Uniform'}, ...
        'sigma', linspace(0,10,101), ...
        'f0', logspace(-2,1,100), ...
        'f1', logspace(1,3,100), ...
        't1', logspace(1,3,100), ...
        'bw', linspace(0,1,101), ...
        'duty', linspace(0,100,101), ...
        'width', linspace(0,1,101), ...
        'name', {'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'}, ...
        'yunits', unit.supportedUnits ...
        ), ...
        'fsdata',   plist(...
        'fsfcn',{'f','1./f', '5./(f.^4) + 2./(f.^2) + 1 + f.^4', 'sinc(f)'}, ...
        'f_mode', {'build', 'list'}, ...
        'f1', logspace(-5,-3,100), ...
        'f2', logspace(-3,1,100), ...
        'nf', logspace(1,5,100), ...
        'scale',{'log','lin'}, ...
        'f', [-6 1], ...
        'name', {'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'}, ...
        'yunits', unit.supportedUnits ...
        ), ...
        'cdata',    plist(...
        'vals', [-1e5 1e5], ...
        'name', {'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'}, ...
        'yunits', unit.supportedUnits), ...
        'xydata',   plist(...
        'xvals', [-1e5 1e5], ...
        'yvals', [-1e5 1e5], ...
        'name', {'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'}, ...
        'xunits', unit.supportedUnits, ...
        'yunits', unit.supportedUnits) ...
        );
      
    case 'plist'
      out_list = plist(...
        'Parameter_01', 1, ...
        'Parameter_02', '2', ...
        'Parameter_03', pi, ...
        'Parameter_04', [1:10]', ...
        'Parameter_05', 'This is really not important', ...
        'Parameter_06', -1/sqrt(2), ...
        'Parameter_07', [1:10]', ...
        'Parameter_08', 0, ...
        'Parameter_09', 1./sqrt(2*pi).*exp(-10:0.1:10), ...
        'Parameter_10', [] ...
        );
      
    case 'mfir'
      out_list = plist(...
        'type', {'highpass', 'lowpass', 'bandpass', 'bandreject'}, ...
        'order', [2:2:100], ...
        'gain', [1:1:1000], ...
        'fs', [0.1:0.1:10], ...
        'fc', [0.01:0.01:0.1], ...
        'iunits', unit.supportedUnits, ...
        'ounits', unit.supportedUnits ...
        );
      
    case 'miir'
      out_list = plist(...
        'type', {'highpass', 'lowpass', 'bandpass', 'bandreject'}, ...
        'order', [1:20], ...
        'gain', [1:1:1000], ...
        'fs', [0.1:0.1:10], ...
        'fc', [0.01:0.01:0.1], ...
        'ripple', [0.5:0.5:2], ...
        'iunits', unit.supportedUnits, ...
        'ounits', unit.supportedUnits ...
        );
      
    case 'pzmodel'
      freq = [0.01:0.01:1];
      Q = [NaN(1,21) logspace(0,3,21)];
      
      out_list = plist(...
        'gain', [1:1:1000], ...
        'freq', freq, ...
        'Q', Q, ...
        'name', {'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight'}, ...
        'iunits', unit.supportedUnits, ...
        'ounits', unit.supportedUnits ...
        );
      
    case 'ssm'
      model_list = {
        'IS_readout_xcpl', ...
        'Interferometer_readout', ...
        'Interferometer_readout_xcpl', ...
        'LPF_Dynamics', ...
        'MPS', ...
        'NSF_IS_readout', ...
        'NSF_Interferometer_readout', ...
        'NSF_MPS', ...
        'NSF_ST_readout', ...
        'NSF_TM', ...
        'NSF_TMActuation', ...
        'NSF_TM_SC', ...
        'NSF_infrared', ...
        'NSF_solar', ...
        'ST_readout', ...
        'TMActuation_xcpl', ...
        'delay', ...
        'delay_IS_readout', ...
        'delay_Ifo_readout', ...
        'delay_ST_readout' ...
        };
      
      out_list = plist('model_list', model_list);
      
    case 'timespan'
      t = time;
      out_list = plist(...
        'timezone', t.getTimezones, ...
        'timeformat', {'yyyy-mm-dd HH:MM:SS.FFF', 'HH:MM:SS', 'yyyy-mm-dd HH:MM:SS'} ...
        );
      
    case 'parfrac'
      out_list = plist(...
        'res', randn(1,100).^3,...
        'poles', -randn(1,100).^2,... % all <0
        'dir', utils.math.randelement([0:3],1),...
        'iunits', unit.supportedUnits, ...
        'ounits', unit.supportedUnits ...
        );
       
     case 'rational'
      out_list = plist(...
        'num', randn(1,100).*utils.math.randelement([-10:10],100),...
        'den', randn(1,100).*utils.math.randelement([-10:10],100),...
        'iunits', unit.supportedUnits, ...
        'ounits', unit.supportedUnits ...
        ); %#ok<*NBRAK>
     
     case 'unsupported'
      % In case of class not supported yet by the repository, the function
      % will provide a plist to create a fixed AO instead.
      out_list = plist(...
        'nsecs', 1000, ...
        'fs', 10, ...
        'noise_type', 'Normal', ...
        'f_m', 0.01, ...
        'phi', 0 ...
        );
      
    otherwise
      error('Unknown class name ''[%s]'' provided', obj)
  end
  
end

%--------------------------------------------------------------------------
% Provides simple AOs with tsdata
%--------------------------------------------------------------------------

function ao_out = prepare_simple_ao(pls)
  % Makes the trial object(s)
  nsecs = find(pls, 'NSECS');
  fs    = find(pls, 'FS');
  f_m   = find(pls, 'F_M');
  phi   = find(pls, 'PHI');
  noise_type = find(pls, 'NOISE_TYPE');
  test_ID = find(pls, 'TEST_ID');
  
  pl_w = plist('fs', fs, 'nsecs', nsecs, ...
    'waveform', 'sine wave','f', f_m, 'phi', phi, 'test_ID', test_ID);
  pl_n = plist('fs', fs, 'nsecs', nsecs, ...
    'waveform', 'noise', 'type', noise_type, 'test_ID', test_ID);
  
  ao_out = ao(pl_w) + ao(pl_n);
end


%--------------------------------------------------------------------------
% Executes the submit/receive actions
%--------------------------------------------------------------------------
function sr_report = submitretrieve(conn, sub_obj, test_ID, coll_retr)
  import utils.const.*;
  
  %% Get the current time
  t1 = char(time());
  
  %% Put togehter the information struct
  sinfo.conn                   = conn;
  sinfo.username               = conn.username;
  sinfo.experiment_title       = ['Repository Test ' t1(1:10)];
  sinfo.experiment_description = sprintf('Submit/retrieve test # %d', test_ID);
  sinfo.analysis_description   = 'Testing constructors, submit, retrieve';
  sinfo.quantity               = 'none';
  sinfo.keywords               = 'none';
  sinfo.reference_ids          = '';
  sinfo.additional_comments    = 'Trial data for submission and retrieval';
  sinfo.additional_authors     = 'M Hewitson';
  
  
  %% Submit the object(s)
  tic;
  [OBJids, cid] = submit(sub_obj{:}, sinfo);
  st = toc;
  
  %% Retrieve the object(s) from xml field
  if coll_retr
    % Retrieve the object(s) by collection ID
    utils.helper.msg(msg.MNAME, '\n%s%d\n%s', ...
      'Retrieve xml object with collection ID ', cid, '  ');
    tic;
    ret_obj_xml = ltpda_uo.retrieve(conn, 'Collection', cid);
  else
    % retrieve the object(s) by obj IDs
    utils.helper.msg(msg.MNAME, '\n%s%s\n%s', ...
      'Retrieve xml object with obj ID ', num2str(OBJids), '  ');
    tic;
    ret_obj_xml = ltpda_uo.retrieve(conn, OBJids);
  end
  
  % Single retrieval will give an object, not a cell array
  if ~isa(ret_obj_xml, 'cell')
    ret_obj_xml = {ret_obj_xml};
  end
  rt_xml = toc;
  
  %% Retrieve the object(s) from binary field
  if coll_retr
    % Retrieve the object(s) by collection ID
    utils.helper.msg(msg.MNAME, '\n%s%d\n%s', ...
      'Retrieve binary object with collection ID ', cid, '  ');
    tic;
    ret_obj_bin = ltpda_uo.retrieve(conn, 'binary', 'Collection', cid);
  else
    % retrieve the object(s) by obj IDs
    utils.helper.msg(msg.MNAME, '\n%s%s\n%s', ...
      'Retrieve binary object with obj ID ', num2str(OBJids), '  ');
    tic;
    ret_obj_bin = ltpda_uo.retrieve(conn, 'binary', OBJids);
  end
  
  % Single retrieval will give an object, not a cell array
  if ~isa(ret_obj_bin, 'cell')
    ret_obj_bin = {ret_obj_bin};
  end
  rt_bin = toc;
  
  %% Check consistency of retrieved/submitted object(s)
  status = zeros(2,length(sub_obj));
  
  for kk = 1:length(sub_obj)
    status(1,kk) = status(1,kk) + ne(sub_obj{kk}, ret_obj_xml{kk}, 'invars', 'hist'); % TODO: remove the hist checking
    status(2,kk) = status(2,kk) + ne(sub_obj{kk}, ret_obj_bin{kk}, 'invars', 'hist'); % TODO: remove the hist checking
  end
  
  % Edit the time field
  t = t1(1:19); % Skip milliseconds
  t(strfind(t,':')) = '_';    % These are correct fieldnames
  
  sr_report = plist(...
    'ret_time_xml', rt_xml, ...
    'ret_time_bin', rt_bin, ...
    'sub_time', st, ...
    't', t, ...
    'test_ID', test_ID, ...
    'status', status, ...
    'OBJids', OBJids, ...
    'cid', cid, ...
    'sinfo', rmfield(sinfo, 'conn') ... % Remove the non-serializable substructs
    );
  
end

%--------------------------------------------------------------------------
% Get Info Object
%--------------------------------------------------------------------------
function ii = getInfo(varargin)
  if nargin == 1 && strcmpi(varargin{1}, 'None')
    sets = {};
    pl   = [];
  else
    sets = {'Default'};
    pl   = getDefaultPlist;
  end
  % Build info object
  ii = minfo(mfilename, 'ao', '', utils.const.categories.helper, '$Id: repo_test_func.m,v 1.6 2009/03/25 17:39:01 nicola Exp $', sets, pl);
end

%--------------------------------------------------------------------------
% Get Default Plist
%--------------------------------------------------------------------------
function plo = getDefaultPlist()
  
  disp('* creating default plist...');
  plo = plist(...
    'RAND_N_OBJ',      false, ...
    'N_OBJ',           1, ...
    'RAND_OBJ_TYPE',   false, ...
    'OBJ_TYPE',        'ao', ...
    'RAND_AO',         true, ...
    'AO_PARAMS',       plist, ...
    'RAND_PLIST',      true, ...
    'PLIST_PARAMS',    plist, ...
    'RAND_MFIR',       true, ...
    'MFIR_PARAMS',     plist, ...
    'RAND_MIIR',       true, ...
    'MIIR_PARAMS',     plist, ...
    'RAND_PZMODEL',    true, ...
    'PZMODEL_PARAMS',  plist, ...
    'RAND_TIMESPAN',   true, ...
    'TIMESPAN_PARAMS', plist, ...
    'RAND_SSM',        true, ...
    'SSM_PARAMS',      plist, ...
    'RAND_PARFRAC',    true, ...
    'PARFRAC_PARAMS',  plist, ...
    'RAND_RATIONAL',   true , ...
    'RATIONAL_PARAMS', plist, ...
    'HOSTNAME',        '130.75.117.67', ...
    'DBASE',           'ltpda_test', ...
    'COLL_RETRIEVE',   false, ...
    'SAVE_OBJS',       true, ...
    'OBJ_FILENAME',    'submit_trial_obj', ...
    'OBJ_FILEFORMAT',  'xml', ...
    'DIR',             '/Users/MH/exper_data/test/obj_creation' , ...
    'SUBMIT',          false, ...
    'CONN',            [], ...
    'SAVE_RESULTS',    true, ...
    'FILESIZE',        false, ...
    'RESULTS_FILENAME','repo_test' ...
    );
  disp('* done.');
end

% END
