time | Calls | line |
---|
| | 1 | function t = setProperty(t,name,p)
|
| | 2 | %SETPROPERTY Set a table property.
|
| | 3 |
|
| | 4 | % Copyright 2012-2019 The MathWorks, Inc.
|
| | 5 |
|
| | 6 | % We may be given a name (when called from set), or a subscript expression
|
| | 7 | % that starts with a '.name' subscript (when called from subsasgn). Get the
|
| | 8 | % name and validate it in any case.
|
| | 9 |
|
| | 10 | import matlab.tabular.Continuity
|
| | 11 |
|
< 0.001 | 8 | 12 | if isstruct(name)
|
< 0.001 | 8 | 13 | s = name;
|
< 0.001 | 8 | 14 | if s(1).type ~= '.'
|
| | 15 | error(message('MATLAB:table:InvalidSubscript'));
|
< 0.001 | 8 | 16 | end
|
< 0.001 | 8 | 17 | name = s(1).subs;
|
< 0.001 | 8 | 18 | haveSubscript = true;
|
| | 19 | else
|
| | 20 | haveSubscript = false;
|
< 0.001 | 8 | 21 | end
|
| | 22 | % Allow partial match for property names if this is via the set method;
|
| | 23 | % require exact match if it is direct assignment via subsasgn
|
0.003 | 8 | 24 | name = tabular.matchPropertyName(name,t.propertyNames,haveSubscript);
|
| | 25 |
|
< 0.001 | 8 | 26 | if haveSubscript && ~isscalar(s)
|
| | 27 | % If this is 1-D named parens/braces subscripting, convert labels to
|
| | 28 | % correct indices for properties that support subscripting with labels.
|
| | 29 | % e.g. t.Properties.RowNames('SomeRowName')
|
| | 30 | if ~strcmp(s(2).type,'.') && isscalar(s(2).subs)
|
| | 31 | sub = s(2).subs{1};
|
| | 32 | if matlab.internal.datatypes.isText(sub) % a name, names, or colon
|
| | 33 | switch name
|
| | 34 | case {'VariableNames' 'VariableDescriptions' 'VariableUnits' 'VariableContinuity'}
|
| | 35 | s(2).subs{1} = t.varDim.subs2inds(sub);
|
| | 36 | case {'RowNames' 'RowTimes'}
|
| | 37 | s(2).subs{1} = t.rowDim.subs2inds(sub);
|
| | 38 | case 'DimensionNames'
|
| | 39 | s(2).subs{1} = t.metaDim.subs2inds(sub);
|
| | 40 | case 'CustomProperties' % Error for any non-dot subscript below t.Properties.CustomProperties
|
| | 41 | error(message('MATLAB:table:InvalidSubscript'))
|
| | 42 | end
|
| | 43 | end
|
| | 44 | end
|
| | 45 |
|
| | 46 | if strcmp(name, 'CustomProperties')
|
| | 47 | % Because CustomProperties can be either per-variable or per-table, they
|
| | 48 | % need to be handled separately. Avoid getProperty and constructing the
|
| | 49 | % object. Instead, work directly on the custom props structs.
|
| | 50 | if isfield(t.varDim.customProps,s(2).subs) % per-variable
|
| | 51 | % We don't allow tables as per-variable properties so the
|
| | 52 | % subsasgnRecursor isn't necessary.
|
| | 53 | isPerVar = true;
|
| | 54 | LHScell = { t.varDim.customProps };
|
| | 55 | s(1).type = '{}'; s(1).subs = {1};
|
| | 56 | % Support assignment to a single variable
|
| | 57 | % (t.Properties.CustomProperties.prop(3) = x), by first filling the
|
| | 58 | % variables with default of the right type and to ensure that
|
| | 59 | % the properties are the same length as the width of the table.
|
| | 60 | if numel(s) > 2
|
| | 61 | % Support named subscript in () or {} on per-variable.
|
| | 62 | s(3).subs{1} = t.varDim.subs2inds(s(3).subs{1});
|
| | 63 | if isequal(size(subsref(LHScell,s(1:2))),[0,0])
|
| | 64 | import matlab.internal.datatypes.defaultarrayLike
|
| | 65 | % Support assigning to a particular element of a previously empty custom property. e.g. t.Properties.CustomProperties.Foo{3} = 'abc'
|
| | 66 | if strcmp(s(3).type,'()')
|
| | 67 | LHScell = builtin('subsasgn',LHScell,s(1:2), defaultarrayLike(size(t.varDim.labels), 'like', p, false));
|
| | 68 | elseif strcmp(s(3).type,'{}')
|
| | 69 | LHScell = builtin('subsasgn',LHScell,s(1:2), defaultarrayLike(size(t.varDim.labels), 'like', {p}, false));
|
| | 70 | end
|
| | 71 | end
|
| | 72 | end
|
| | 73 | LHScell = builtin('subsasgn',LHScell,s,p);
|
| | 74 | elseif isfield(t.arrayProps.TableCustomProperties,s(2).subs) % per-table
|
| | 75 | isPerVar = false;
|
| | 76 | LHScell = { t.arrayProps.TableCustomProperties };
|
| | 77 | s(1).type = '{}'; s(1).subs = {1};
|
| | 78 | % Per-table CustomProperties may be a table, so need
|
| | 79 | % subsasgnRecursor to break the chain.
|
| | 80 | LHScell = matlab.internal.tabular.private.subsasgnRecurser(LHScell,s,p);
|
| | 81 | else
|
| | 82 | error(message('MATLAB:table:InvalidCustomPropName'))
|
| | 83 | end
|
| | 84 | else
|
| | 85 | % If there's cascaded subscripting into the property, get the existing
|
| | 86 | % property value and let the property's subsasgn handle the assignment.
|
| | 87 | % The property may currently be empty, ask for a non-empty default
|
| | 88 | % version to allow assignment into only some elements. Guarantee correct
|
| | 89 | % dispatch for the assignment by working inside a scalar cell and letting
|
| | 90 | % built-in cell subscripting dispatch.
|
| | 91 | LHScell = { t.getProperty(name,true) };
|
| | 92 |
|
| | 93 | s(1).type = '{}'; s(1).subs = {1};
|
| | 94 |
|
| | 95 | if strcmp(name,'UserData')
|
| | 96 | LHScell = matlab.internal.tabular.private.subsasgnRecurser(LHScell,s,p);
|
| | 97 | else
|
| | 98 | % We want to catch assigning '' into the variable properties using parens
|
| | 99 | % to throw a better error message. Assigning '' into an array means
|
| | 100 | % deletion, but it most likely wasn't the user's intention for these
|
| | 101 | % properties - they probably wanted to assign empty. Deleting a single
|
| | 102 | % value from variable properties is not a possible operation since the
|
| | 103 | % number of variable properties must match the number of variables. Thus,
|
| | 104 | % an error will be thrown for incorrect number of continuity later on,
|
| | 105 | % which will be confusing. Throw a better error here instead.
|
| | 106 | if ~isstring(p) && isequal(p,'') && strcmp(s(2).type,'()')
|
| | 107 | if any(strcmp(name,{'VariableNames' 'VariableDescriptions' 'VariableUnits'}))
|
| | 108 | error(message('MATLAB:invalidConversion','cell','char'));
|
| | 109 | elseif strcmp(name,'VariableContinuity')
|
| | 110 | error(message('MATLAB:table:InvalidContinuityValue'));
|
| | 111 | end
|
| | 112 | end
|
| | 113 |
|
| | 114 | % Okay to convert strings because UserData and CustomProperties do
|
| | 115 | % not go through here.
|
| | 116 | p = matlab.internal.datatypes.stringToLegacyText(p,true); % scalarCellOutput = true
|
| | 117 |
|
| | 118 | try
|
| | 119 | LHScell = builtin('subsasgn',LHScell,s,p);
|
| | 120 | catch ME
|
| | 121 | if strcmp(ME.identifier,'MATLAB:UnableToConvert') && strcmp(name,'VariableContinuity')
|
| | 122 | % Need to check for invalid enum value, for better error message.
|
| | 123 | error(message('MATLAB:table:InvalidContinuityValue'));
|
| | 124 | else
|
| | 125 | rethrow(ME);
|
| | 126 | end
|
| | 127 | end
|
| | 128 | end
|
| | 129 | end
|
| | 130 | p = LHScell{1};
|
| | 131 | % The assignment may change the property's shape or size or otherwise make
|
| | 132 | % it invalid; that gets checked by the individual setproperty methods called
|
| | 133 | % below.
|
< 0.001 | 8 | 134 | else
|
| | 135 | % If we are not assigning into property, we want to error in one specific
|
| | 136 | % case, when the assignment is for the whole VariableContinuity property
|
| | 137 | % and the value being assigned is character vector.
|
< 0.001 | 8 | 138 | if ischar(p) && strcmp(name,'VariableContinuity')
|
| | 139 | error(message('MATLAB:table:InvalidContinuityFullAssignment'));
|
< 0.001 | 8 | 140 | end
|
< 0.001 | 8 | 141 | end
|
| | 142 |
|
| | 143 | % Assign the new property value into the dataset.
|
< 0.001 | 8 | 144 | try
|
< 0.001 | 8 | 145 | switch name
|
< 0.001 | 8 | 146 | case {'RowNames' 'RowTimes'}
|
0.015 | 8 | 147 | t.rowDim = t.rowDim.setLabels(p); % error if duplicate, or empty
|
| | 148 |
|
| | 149 | % These three have already been verified present by matchPropertyName
|
| | 150 | case 'StartTime'
|
| | 151 | t.rowDim = t.rowDim.setStartTime(p);
|
| | 152 | case 'TimeStep'
|
| | 153 | t.rowDim = t.rowDim.setTimeStep(p);
|
| | 154 | case 'SampleRate'
|
| | 155 | t.rowDim = t.rowDim.setSampleRate(p);
|
| | 156 |
|
| | 157 | case 'VariableNames'
|
| | 158 | t.varDim = t.varDim.setLabels(p); % error if invalid, duplicate, or empty
|
| | 159 | % Check for conflicts between the new VariableNames and the existing
|
| | 160 | % DimensionNames. For backwards compatibility, a table will modify
|
| | 161 | % DimensionNames and warn, while a timetable will error.
|
| | 162 | t.metaDim = t.metaDim.checkAgainstVarLabels(t.varDim.labels);
|
| | 163 | case 'DimensionNames'
|
| | 164 | t.metaDim = t.metaDim.setLabels(p); % error if duplicate, or empty
|
| | 165 | % Check for conflicts between the new DimensionNames and the existing
|
| | 166 | % VariableNames.
|
| | 167 | t.metaDim = t.metaDim.checkAgainstVarLabels(t.varDim.labels);
|
| | 168 | case 'VariableDescriptions'
|
| | 169 | t.varDim = t.varDim.setDescrs(p);
|
| | 170 | case 'VariableUnits'
|
| | 171 | t.varDim = t.varDim.setUnits(p);
|
| | 172 | case 'VariableContinuity'
|
| | 173 | % Assigning single character vector to whole VariableContinuity property
|
| | 174 | % should already be caught above.
|
| | 175 | t.varDim = t.varDim.setContinuity(p);
|
| | 176 | case 'Description'
|
| | 177 | t = t.setDescription(p);
|
| | 178 | case 'UserData'
|
| | 179 | t = t.setUserData(p);
|
| | 180 | case 'CustomProperties'
|
| | 181 | if ~haveSubscript || isscalar(s)
|
| | 182 | if isa(p,'matlab.tabular.CustomProperties')
|
| | 183 | % t.Properties.CustomProperties = p
|
| | 184 | % Assign CustomProperties object back into table.
|
| | 185 | [vnames, tnames] = getNames(p);
|
| | 186 | % First clear custom properties
|
| | 187 | t.varDim = t.varDim.setCustomProps(struct);
|
| | 188 | t.arrayProps.TableCustomProperties = struct;
|
| | 189 | for ii = 1:numel(vnames)
|
| | 190 | t.varDim = t.varDim.setCustomProp(p.(vnames{ii}),vnames{ii});
|
| | 191 | end
|
| | 192 | for ii = 1:numel(tnames)
|
| | 193 | t = t.setPerTableProperty(p.(tnames{ii}),tnames{ii});
|
| | 194 | end
|
| | 195 | else
|
| | 196 | error(message('MATLAB:table:InvalidCustomPropertiesAssignment'))
|
| | 197 | end
|
| | 198 | else
|
| | 199 | % Deeper assignment to a particular custom property. The
|
| | 200 | % subscripted assignment was already done above, and it was
|
| | 201 | % determined whether it is per-var or per-table, so just do
|
| | 202 | % the assignment here.
|
| | 203 | propName = s(2).subs;
|
| | 204 | if isPerVar
|
| | 205 | t.varDim = t.varDim.setCustomProp(p.(propName), propName);
|
| | 206 | else % isPerTable
|
| | 207 | t = t.setPerTableProperty(p.(propName), propName);
|
| | 208 | end
|
| | 209 | end
|
< 0.001 | 8 | 210 | end
|
| | 211 | catch ME
|
| | 212 | % Distinguish between full-assignment and partial assignment of variable
|
| | 213 | % names and throw different messages.
|
| | 214 | if strcmp(ME.identifier,'MATLAB:table:InvalidVarNames') && (haveSubscript && ~isscalar(s)) && strcmp(s(2).type,'{}')
|
| | 215 | error(message('MATLAB:table:InvalidVarNameBraces'));
|
| | 216 | else
|
| | 217 | rethrow(ME)
|
| | 218 | end
|
< 0.001 | 8 | 219 | end
|
Other subfunctions in this file are not included in this listing.