function varargout = subsref( obj, S )
%SUBSREF Composite subsref method retrieves remote values
%   B = C(I) returns the entry of Composite C from lab I as a cell array
%   B = C([I1, I2, ...]) returns multiple entries as a cell array
%
%   B = C{I} returns a single entry
%   [B1, B2, ...] = C{[I1, I2, ...]} returns multiple entries
    
% Copyright 2008-2012 The MathWorks, Inc.

    if strcmp( S(1).type, '.' )
        error(message('parallel:lang:spmd:CompositeSubsrefNoDotRef'));
    end
    
    % composites do not support multiple levels of subscripting.
    if length( S ) ~= 1
        error(message('parallel:lang:spmd:CompositeSubsrefOnlySimple'));
    end
    
    % Error early in the case where the pool is closed
    if ~obj.isResourceSetOpen()
        error(message('parallel:lang:spmd:CompositeSubsrefInvalid'));
    end

    switch S.type
      case '()'
        if nargout > 1
            error(message('parallel:lang:spmd:CompositeSubsrefNargout', nargout));
        end

        try
            % Defer to builtin indexing of the key vector
            keyHolderCell = obj.KeyVector( S.subs{:} );
            ret           = cell( size( keyHolderCell ) );
            
            % Check before actually making the remote call
            labs = iCheckValuesExist( obj, S.subs{:} );
            
            for ii=1:length( keyHolderCell )
                ret{ii} = obj.getValOrError( keyHolderCell{ii}, labs(ii) );
            end
            varargout{1}  = ret;
        catch E
            EE = MException(message('parallel:lang:spmd:CompositeSubsrefInvalidRequest'));
            EE = addCause( EE, E );
            throw( EE );
        end
      case '{}'
        try
            % Defer to builtin indexing of the key vector
            keyHolderCell = cell( 1, nargout );
            varargout     = cell( 1, nargout );
            [keyHolderCell{1:nargout}] = obj.KeyVector{ S.subs{:} };

            % Check before actually making the remote call
            labs = iCheckValuesExist( obj, S.subs{:} );

            for ii=1:length( keyHolderCell )
                varargout{ii} = obj.getValOrError( keyHolderCell{ii}, labs(ii) );
            end
        catch E
            EE = MException(message('parallel:lang:spmd:CompositeSubsrefInvalidRequest'));
            EE = addCause( EE, E );
            throw( EE );
        end

      otherwise
        % Never get here - '.' indexing already handled.
        error(message('parallel:lang:spmd:CompositeSubsrefUnexpectedRequest'));
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% iCheckValuesExist - use Composite.exist to check before we attempt to
% retrieve things whether the values exist
function labsRequested = iCheckValuesExist( obj, varargin )
    allLabs       = 1:length( obj );
    labsRequested = allLabs( varargin{:} );

    % See if any labs don't have a value
    labsNoValue   = labsRequested( ~exist( obj, labsRequested ) );
    if ~isempty( labsNoValue )
        error(message('parallel:lang:spmd:CompositeSubsref', sprintf( '%d ', labsNoValue )));
    end
end
