%AbstractTaskResult
% A data class that stores the results of a partitioned Task.

%   Copyright 2014-2016 The MathWorks, Inc.

classdef (Abstract, Hidden) AbstractTaskResult < handle
    properties (SetAccess = immutable)
        KeyType = ''; % The key type of the map task output.
        ValueType = ''; % The value type of the map task output.
    end
    
    methods
        % Set the immutable state to do with type information.
        function this = AbstractTaskResult(keyType, valueType)
            if nargin
                this.KeyType = keyType;
                this.ValueType = valueType;
            end
        end 
    end
    
    methods (Abstract)
        % Combine two children of this class.
        output = vertcat(varargin);
    end
    
    methods (Access = protected)
        % Combine the type information of all task result objects, issuing an error
        % if the corresponding types do not match.
        function [keyType, valueType] = combineTypes(varargin)
            import parallel.internal.mapreduce.MapTaskResult;
            
            keyType = [];
            valueType = [];
            for ii = 1:nargin
                nextResult = varargin{ii};
                if isempty(nextResult)
                    continue;
                end
                
                if isempty(keyType) && ~isempty(nextResult.KeyType)
                    keyType = nextResult.KeyType;
                elseif ~isempty(keyType) && ~isempty(nextResult.KeyType)
                    if ~strcmp(keyType, nextResult.KeyType)
                        error(message('parallel:mapreduce:MismatchedKeyType', keyType, nextResult.KeyType));
                    end
                end

                if isempty(valueType) && ~isempty(nextResult.ValueType)
                    valueType = nextResult.ValueType;
                elseif ~isempty(valueType) && ~isempty(nextResult.ValueType)
                    if ~strcmp(valueType, nextResult.ValueType)
                        error(message('parallel:mapreduce:MismatchedValueType', valueType, nextResult.ValueType));
                    end
                end
            end
        end
    end
end
