% Implementation of AbstractRemoteCompositeAssistant backed by java classes

% Copyright 2020 The MathWorks, Inc.

classdef JavaRemoteCompositeAssistant < parallel.internal.pool.AbstractRemoteCompositeAssistant

    properties (SetAccess = immutable, GetAccess = private)
        % Java implmentation of RemoteCompositeAssistant
        RemoteCompositeAssistant
    end
    
    methods (Access = private)
        function obj = JavaRemoteCompositeAssistant(remoteCompositeAssistant)
            obj.RemoteCompositeAssistant = remoteCompositeAssistant;
        end
    end
    
    methods (Static)
        function assistant = create(session, processIndices)
            % Create java backed RemoteCompositeAssistant and acquire the specified
            % processes. These process will be released on delete.
            javaAssistant = session.getCompositeAssistant();
            try
                javaAssistant.acquireProcesses(processIndices);
            catch E
                % Our own CallableExecutionException wraps the original exception, so unwrap it here
                if isa(E, 'com.mathworks.toolbox.distcomp.util.CallableExecutionException')
                    cause = E.getCause();
                    rethrow(cause);
                else
                    rethrow(E);
                end
            end
            assistant = parallel.internal.pool.JavaRemoteCompositeAssistant(javaAssistant);
        end
    end
    
    methods
        function delete(obj)
            obj.RemoteCompositeAssistant.releaseProcesses();
        end
    end
    
    % Implement AbstractRemoteCompositeAssistant methods
    methods 
        function future = retrieveCompositeValue(obj, processIndex, key)
            observer = obj.RemoteCompositeAssistant.retrieveCompositeValue(processIndex, distcompserialize(key));
            future = parallel.internal.pool.JavaRemoteFuture(observer);
        end
        
        function future = sendCompositeValue(obj, processIndex, value)
            bbufh = parallel.internal.pool.serialize(value);
            observer = obj.RemoteCompositeAssistant.sendCompositeValue(processIndex, bbufh);
            future = parallel.internal.pool.JavaRemoteFuture(observer);
        end
        
        function future = clearCompositeValues(obj, processIndex)
            observer = obj.RemoteCompositeAssistant.clearCompositeValues(processIndex);
            future = parallel.internal.pool.JavaRemoteFuture(observer);
        end
        
        function tf = hasKeysToClear(obj, processIndex)
            tf = obj.RemoteCompositeAssistant.hasKeysToClear(processIndex);
        end
    end
end

