gusucode.com > datatypes 工具箱matlab源码程序 > datatypes/+matlab/+internal/+table/tableMetaDim.m
classdef (Sealed) tableMetaDim < matlab.internal.table.tableDimension %TABLEMETASDIM Internal class to represent a table's list of dimension. % This class is for internal use only and will change in a % future release. Do not use this class. % Copyright 2016 The MathWorks, Inc. properties(Constant, GetAccess=public) propertyNames = {'DimensionNames'}; end properties(GetAccess=public, SetAccess=protected) dispRowHeader = false; end properties(GetAccess=protected, SetAccess=private) % This property controls whether validation of dim names is lenient for backwards % compatibility, see checkAgainstVarLabels and fixLabelsForCompatibility for more details. backwardsCompatibility = false; end methods function obj = tableMetaDim(length,labels,dispRowHeader,backwardsCompatibility) % Technically, this is not a table dimension, it's more like a table % meta-dimension. But it's close enough to var and row names to % reuse the infrastructure. Always initialize with two default % names, and orient them alons dim=2, as a row. import matlab.internal.datatypes.isCharStrings if nargin == 0 length = 2; labels = matlab.internal.table.dfltDimNames; elseif nargin == 1 labels = matlab.internal.table.dfltDimNames; else % This is the relevant parts of validateAndAssignLabels if ~isCharStrings(labels,true,false) % require cellstr, no empties error(message('MATLAB:table:InvalidDimNames')); end labels = strtrim(labels(:)'); % a row vector, conveniently forces any empty to 0x1 if (nargin > 3) && backwardsCompatibility % tables, for now labels = fixLabelsForCompatibility(labels); else % timetables matlab.internal.tableUtils.makeValidName(labels,'dimnamesError'); matlab.internal.table.checkDuplicateNames(labels,'dimnames'); matlab.internal.table.checkReservedNames(labels,'dimnames'); end end obj = obj@matlab.internal.table.tableDimension(2,length,true,true,labels); if nargin > 2 obj.dispRowHeader = dispRowHeader; if nargin > 3 obj.backwardsCompatibility = backwardsCompatibility; end end end %----------------------------------------------------------------------- function labels = defaultLabels(obj,indices) if nargin < 2 indices = 1:obj.length; end labels = matlab.internal.table.dfltDimNames(indices); end %----------------------------------------------------------------------- function obj = lengthenTo(obj,~,~) assert(false); end %----------------------------------------------------------------------- function s = getProperties(obj) % Same order as tableMetaDim.propertyNames s.DimensionNames = obj.labels; end %----------------------------------------------------------------------- function obj = checkAgainstVarLabels(obj,varLabels,errorMode) import matlab.internal.tableUtils.warningWithoutTrace % Pre-2016b, DimensionNames were not required to be distinct from VariableNames, % but now they are. If they conflict, modify DimensionNames and warn. [modifiedLabels,wasConflicted] = matlab.lang.makeUniqueStrings(obj.labels,varLabels,namelengthmax); if any(wasConflicted) if nargin > 2 switch errorMode case 'silent' % OK case 'warn' warningWithoutTrace(message('MATLAB:table:DuplicateDimNamesVarNamesWarn',obj.labels{find(wasConflicted,1)})); case 'error' error(message('MATLAB:table:DuplicateDimNamesVarNames',obj.labels{find(wasConflicted,1)})); otherwise assert(false); end elseif obj.backwardsCompatibility % tables, for now warningWithoutTrace(message('MATLAB:table:DuplicateDimnamesVarnamesBackCompat',obj.labels{find(wasConflicted,1)})); else % timetables error(message('MATLAB:table:DuplicateDimNamesVarNames',obj.labels{find(wasConflicted,1)})); end obj.labels = modifiedLabels; end end end %=========================================================================== methods (Access=protected) function obj = validateAndAssignLabels(obj,newLabels,dimIndices,fullAssignment,fixDups,fixEmpties,fixIllegal) import matlab.internal.datatypes.isCharString import matlab.internal.datatypes.isCharStrings if ~fullAssignment && isCharString(newLabels,fixEmpties) % Accept one character vector for (partial) assignment to one name, allow empty character vectors per caller. newLabels = { strtrim(newLabels) }; elseif isCharStrings(newLabels,true,fixEmpties) % Accept a cellstr, allow empty character vectors per caller. newLabels = strtrim(newLabels(:)'); % a row vector, conveniently forces any empty to 0x1 else error(message('MATLAB:table:InvalidDimNames')); end % Fill in empty names if allowed, and make them unique with respect % to the other new names. If not allowed, an error was already thrown. [newLabels,wasEmpty] = fillEmptyNames(newLabels,dimIndices); newLabels = matlab.lang.makeUniqueStrings(newLabels,wasEmpty,namelengthmax); if fixIllegal newLabels = matlab.internal.tableUtils.makeValidName(newLabels,'dimnamesWarn'); else if obj.backwardsCompatibility % tables, for now newLabels = fixLabelsForCompatibility(newLabels); else % timetables newLabels = matlab.internal.tableUtils.makeValidName(newLabels,'dimnamesError'); end end matlab.internal.table.checkReservedNames(newLabels,'dimnames'); if fixDups % Make the new names (in their possibly modified form) unique with respect to % each other and to existing names. allNewLabels = obj.labels; allNewLabels(dimIndices) = newLabels; allNewLabels = matlab.lang.makeUniqueStrings(allNewLabels,dimIndices,namelengthmax); newLabels = allNewLabels(dimIndices); elseif fullAssignment % Check that the whole set of new names is unique matlab.internal.table.checkDuplicateNames(newLabels,'dimnames'); else % Make sure empty new names that were filled in or modified do not duplicate any % of the other new names. newLabels = matlab.lang.makeUniqueStrings(newLabels,wasEmpty,namelengthmax); % Check that the new names do not duplicate each other or existing names. allNewLabels = obj.labels; allNewLabels(dimIndices) = newLabels; matlab.internal.table.checkDuplicateNames(newLabels,allNewLabels,dimIndices,'dimnames'); end obj = obj.assignLabels(newLabels,fullAssignment,dimIndices); end %----------------------------------------------------------------------- function obj = makeUniqueForRepeatedIndices(obj,~) assert(false); end %----------------------------------------------------------------------- function throwRequiresLabels(obj) %#ok<MANU> msg = message('MATLAB:table:CannotRemoveDimNames'); throwAsCaller(MException(msg.Identifier,msg.getString())); end function throwInvalidPartialLabelsAssignment(obj) %#ok<MANU> assert(false); end function throwIncorrectNumberOfLabels(obj) %#ok<MANU> msg = message('MATLAB:table:IncorrectNumberOfDimNames'); throwAsCaller(MException(msg.Identifier,msg.getString())); end function throwIncorrectNumberOfLabelsPartial(obj) %#ok<MANU> msg = message('MATLAB:table:IncorrectNumberOfDimNamesPartial'); throwAsCaller(MException(msg.Identifier,msg.getString())); end function throwIndexOutOfRange(obj) %#ok<MANU> msg = message('MATLAB:table:DimIndexOutOfRange'); throwAsCaller(MException(msg.Identifier,msg.getString())); end function throwUnrecognizedLabel(obj,label) %#ok<INUSL> msg = message('MATLAB:table:UnrecognizedDimName',label{1}); throwAsCaller(MException(msg.Identifier,msg.getString())); end function throwInvalidLabel(obj) %#ok<MANU> msg = message('MATLAB:table:InvalidDimName'); throwAsCaller(MException(msg.Identifier,msg.getString())); end function throwInvalidSubscripts(obj) %#ok<MANU> msg = message('MATLAB:table:InvalidDimSubscript'); throwAsCaller(MException(msg.Identifier,msg.getString())); end end end %----------------------------------------------------------------------- function labels = fixLabelsForCompatibility(labels) % Pre-R2016b, DimensionNames had almost no constraints, but there are new % requirements to support new dot subscripting functionality added in R2016b. % The old defaults met those requirements, so if the names are not (now) valid, % they must have been intentionally changed from their old defaults (or perhaps % DimensionNames{1} came from a column header in a file). In any case, to avoid % breaking existing table code, modify any invalid names and warn. import matlab.internal.tableUtils.warningWithoutTrace originalLabels = labels; % Pre-R2016b,names were not required to be valid MATLAB identifiers. [labels,wasMadeValid] = matlab.internal.tableUtils.makeValidName(labels,'silent'); if any(wasMadeValid) warningWithoutTrace(message('MATLAB:table:DimNameNotValidIdentifierBackCompat',originalLabels{find(wasMadeValid,1)})); end % Pre-2016b, names were not required to be distinct from the list of reserved names. wasReserved = matlab.internal.table.checkReservedNames(labels,'dimnames'); if any(wasReserved) warningWithoutTrace(message('MATLAB:table:DimnamesReservedNameConflictBackCompat',originalLabels{find(wasReserved,1)})); labels(wasReserved) = matlab.lang.makeUniqueStrings(labels(wasReserved),labels(wasReserved),namelengthmax); end end %----------------------------------------------------------------------- function [names,empties] = fillEmptyNames(names,indices) empties = cellfun('isempty',names); if any(empties) names(empties) = matlab.internal.table.dfltDimNames(indices(empties)); end end