function c = parcluster( profile )
%PARCLUSTER Build a Cluster from a cluster profile
%   OUT = parcluster returns a cluster object representing the cluster
%   identified by the default cluster profile, with the cluster object
%   properties set to the values defined in that profile.
%
%   OUT = parcluster(PROFILE) returns a cluster object representing the
%   cluster identified by the cluster profile with the specified name, with
%   the cluster object properties set to the values defined in that
%   profile.
%
%   Profiles can be created and changed using the saveProfile or
%   saveAsProfile methods on a cluster object.  Profiles can be created,
%   deleted, and changed using  the Cluster Profiles Manager.  On the Home
%   tab, in the Environment section, click Parallel > Manage Cluster
%   Profiles... to open the Cluster Profiles Manager.
%
%   Examples: 
%   % Find the cluster identified by the default parallel computing cluster 
%   % profile, with the cluster object properties set to the values defined 
%   % in that profile.
%   myCluster = parcluster();
%
%   % View the name of the default profile and find the cluster identified 
%   % by it.
%   defaultProfile = parallel.defaultClusterProfile()
%   myCluster = parcluster(defaultProfile);
%   
%   % Find a particular cluster using the profile named 'MyProfile'.
%   myCluster = parcluster('MyProfile');
%
%   See also PARPOOL, BATCH, parallel.defaultClusterProfile, 
%            parallel.clusterProfiles, parallel.Cluster.saveProfile, 
%            parallel.Cluster.saveAsProfile.

% Copyright 2011-2019 The MathWorks, Inc.

parallel.internal.pool.errorIfPoolThreadWorker(mfilename);
if nargin < 1
    s = parallel.Settings;
    profile = s.DefaultProfile;
end

% Convert any string inputs to character vectors
profile = convertStringsToChars(profile);

try
    type = parallel.internal.settings.ProfileExpander.getClusterType( profile );
catch E
    throw( E );
end

if ~type.isSupported()
    if nargin < 1
        msg = message('parallel:cluster:MatlabOnlineNoDefaultProfile');
    else
        msg = message('parallel:cluster:MatlabOnlineUnsupportedProfileType', type.Name);
    end
    throwAsCaller(MException(msg));
end

try
    builder = iGetBuilderFromClassName( type );
    if type.RequiresLogin
        % The scheduler type dictates the license category to apply
        licenseCategory = type.LicenseCategory;
        parallel.internal.mwa.ensureLoggedInAndRegistered( licenseCategory );
    end
    c = builder( 'Profile', profile );
catch E
    throw( E );
end

end


function builder = iGetBuilderFromClassName(type)
% NB Don't use str2func for the builder so that we don't
% confuse depfun (for compiled application support)
    import parallel.internal.types.SchedulerType
    switch type
      case SchedulerType.Generic
        builder = @parallel.cluster.Generic;
      case SchedulerType.GenericR2016b
        builder = @parallel.cluster.Generic;
      case SchedulerType.HPCServer
        builder = @parallel.cluster.HPCServer;
      case SchedulerType.Local
        builder = @parallel.cluster.Local;
      case SchedulerType.LSF
        builder = @parallel.cluster.LSF;
      case SchedulerType.MJS
        builder = @parallel.cluster.MJS;
      case SchedulerType.MJSComputeCloud
        builder = @parallel.cluster.MJSComputeCloud;
      case SchedulerType.PBSPro
        builder = @parallel.cluster.PBSPro;
      case SchedulerType.Slurm
        builder = @parallel.cluster.Slurm;
      case SchedulerType.Torque
        builder = @parallel.cluster.Torque;
      otherwise
        error(message('parallel:cluster:UnsupportedType', type.Name));
    end
end
