www.gusucode.com > external 工具箱matlab源码程序 > external/interfaces/webservices/http/+matlab/+net/+http/MediaType.m
classdef MediaType < matlab.mixin.CustomDisplay %MediaType an Internet media type used in HTTP headers % An Internet media-type as defined in RFC 7231, <a href="http://tools.ietf.org/html/rfc7231#section-3.1.1">Section 3.1.1.1</a> is commonly % portrayed as a string containing a type and subtype, followed by one or more % optional parameters, each preceded by a semicolon: % % type/subtype; param1=value1; param2=value2 ... % % The type, subtype and param names are tokens containing characters from a % restricted set, and the values are tokens or quoted strings. % % This class models a media-type. The constructor parses a media-type string as % it might appear in an HTTP ContentTypeFIeld and the string method converts it % back to a string. To obtain a MediaType from a ContentTypeField, use the % convert method. % % This class is also used to represent the media-range and accept-params in an % AcceptField. The media-range has the same syntax as media-type and % accept-params that may follow it are not part of the Internet media type (see % RFC 7231, <a href="http://tools.ietf.org/html/rfc7231#section-5.3.2">Section 5.3.2</a>). These additional parameters always begin with a % weight parameter of the form, "q=qvalue" where qvalue is a number: % % type/subtype; param1=value1; param2=value2 ...; q=0.5; ap1=av1; ap2=av2 % \____________________media-type_______________/ \___ accept-params____/ % % The MediaInfo property returns just the media-type portion of a MediaType. % Otherwise, this class treats all parameters similarly and does not distinguish % between media-type parameters and accept-params. When constructing a % MediaType to be used in an AcceptField, you are responsible for ordering % parameters such that the accept-params always follow the "q" parameter. % % MediaType properties: % % Type - (string) the primary type % Subtype - (string) the subtype % Parameters - (string matrix) the parameter names and values. The same % name may appear more than once, but most implementations % only use the last one. % MediaInfo - (MediaType, read-only) returns media-type portion % Weight - (double) numeric value of q parameter % % Except for special handling of the Weight property, this class does not % enforce anything about or interpret values of the properties. % % MediaType methods: % % MediaType - constructor % setParameter - set parameter value % getParameter - get parameter value % isequal, eq, == - compare two MediaType arrays % string, char - convert to string or character vector % % See also matlab.net.http.field.ContentTypeField, matlab.net.http.field.AcceptField % Copyright 2015-2016 The MathWorks, Inc. properties % Type - the primary type (string) % This value is never empty. Type string % Subtype - the subtype (string) % This value is never empty. Subtype string end properties (SetAccess=private) % Parameters - the parameters (n-by-2 string matrix) % Parameters(i,1) is the name of the i'th parameter Parameters(i,2) is the % value of the i'th parameter. You cannot set this array directly: use the % setParameter method to remove, add or change parameter values. To reorder % parameters, construct a new MediaType with the desired parameters from an % an existing MediaType. % % See also setParameter Parameters = string.empty(0,2) end properties (Dependent, SetAccess=immutable) % MediaInfo - return the media-type portion of this object as a MediaType % This returns this object minus all the parameters at or following the % first 'q' parameter. % % See also Parameters MediaInfo end properties (Dependent) % Weight - the value of the weight (q) parameter as a double % This is empty if there is no q parameter and NaN if the parameter % cannot be converted to a double. If you set this property, it must % have a value in the range 0-1, and will modify the final q parameter in % this object (or add one to the end of the parameter list). % % To obtain the exact string that is used to represent this Weight value, % see Parameters or use getParameter('q'). % % See also Parameters, getParameter Weight double end methods function obj = MediaType(type, varargin) % MediaType constructor % MEDIATYPE = MediaType(TYPE, NAME1, VALUE1, ...) creates a MediaType given % the TYPE with optional parameters. The TYPE must be a string or character % vector with the syntax 'type/subtype' and the NAME arguments must be % nonempty strings or character vectors. The VALUE arguments must be % nonempty strings or types acceptable to the string function. If a VALUE % contains characters that need to be quoted or escaped, that will happen % when you use the string method to convert this MediaType to a string. Do % not include quotes or escape characers within a VALUE. % % MEDIATYPE = MediaType(STRING) parses the STRING to create a MEDIATYPE. % Quotes and escape characters within the values of parameters will be % processed out. % % This constructor does not prevent creating a MediaType with duplicate % parameter names. % The following behavior is for internal use only. It may change in a future % release. % MEDIATYPE = MediaType(TYPE, PARAMS) constructs a MEDIATYPE from a TYPE % and Nx2 string matrix of parameter names and values. PARAMS(i,1) is the % name and PARAMS(i,2) is the value. This syntax does not throw an error % if the TYPE is invalid. N may be 0. % MEDIATYPE = MediaType(TYPE, string.empty) constructs a MEDIATYPE from a % TYPE, with no parameters (i.e., TYPE is just type/subtype), and throws % errors if invalid. import matlab.net.internal.getString if nargin == 0, return, end % allow empty array % first arg is TYPE or STRING type = getString(type, mfilename, 'TYPE'); if type=='' error(message('MATLAB:http:BadMediaType',char(type))); else end if nargin > 1 && (length(varargin) > 1 || ... (length(varargin) == 1 && (ischar(varargin{1}) || isscalar(varargin{1})))) % first store/validate the type/subtype [obj.Type, obj.Subtype] = getTypeAndSubtype(type, false); % MediaType(TYPE, NAME, VALUE, ...) % go backwards through arg list to preallocate nargs = length(varargin); for i = nargs - 1 + mod(nargs,2): -2 : 1 name = getName(varargin{i}); if isempty(name) error(message(... 'MATLAB:http:ArgMustBeString', num2str(2*i))); end if i+1 > nargs error(message(... 'MATLAB:webservices:MissingValue', char(name))); end param = createParam(name, varargin{i+1}, false); obj.Parameters((i+1)/2,:) = param; end else if nargin == 1 % MediaType(STRING) and MediaType(TYPE) with no optional args % are functionally equivalent. If it's just TYPE, the following % returns just one row, v(1,1) and v(1,2) v = matlab.net.http.internal.elementParser(type, true, true); if ~isempty(v) if v(1,1)~='' % This happens if the TYPE or first element in the % string is of the NAME=VALUE form instead of % type/subtype error(message('MATLAB:http:BadMediaType', ... char(v(1,1) + '=' + v(1,2)))); end type = v(1,2); params = v(2:end,:); end silent = false; else % nargin == 2, internal use only % MediaType(TYPE, PARAMS) params = varargin{1}; if ~isstring(params) || ~ismatrix(params) || ... (~isempty(params) && size(params,2) ~= 2) % not Nx2 string or string.empty; generate same error as if user % specified illegal value for fisrt param name error(message('MATLAB:http:ArgMustBeString', 2)); end if size(params,2) == 2 % Nx2 string: prevent syntax error message, even if N is 0 silent = true; else % string.empty silent = false; end end [obj.Type, obj.Subtype] = getTypeAndSubtype(type, silent); if ~isempty(params) nparams = size(params,1); obj.Parameters = strings(nparams,2); for i = 1 : nparams name = params(i,1); value = params(i,2); if name=='' || value=='' error(message('MATLAB:http:BadParameter', ... char(name+value))); end obj.Parameters(i,:) = createParam(name, value, silent); end end end end function value = getParameter(obj, name) % getParameter Return the value of a parameter % VALUE = getParameter(OBJ, NAME) returns the value of the named parameter. % VALUE is an array of nonempty strings. It may contain multiple elements % if the parameter appears more than once. Returns an empty array if the % parameter does not exist. Parameter name matching is case-insensitive. % % See also setParameter name = matlab.net.internal.getString(name, mfilename, 'NAME'); match = lower(obj.Parameters(:,1)) == lower(name); value = obj.Parameters(match,2); end function obj = setParameter(obj, name, value) % setParam Set a MediaType parameter % NEWTYPE = setParameter(MEDIATYPE, NAME, VALUE) returns a copy of the % MEDIATYPE with the parameter NAME set to VALUE, adding it if it doesn't % exist. Parameter name matching is case-insensitive. If a parameter % already exists with the same name but different case, the case will be % changed to the specified name. If more than one match is found, only the % last one is set. If the value is empty or an empty string, the parameter % is removed. VALUE may be a scaler string, character vector, or any type % supporting the string method. The resulting string must not be empty. % % If you add a new parameter, it is added to the end of the list of % parameters. This is important if there is already a "q" parameter in the % list, as the new parameter will be treated as part of the accept-params % rather than the media-type. % % There is no validation of VALUE. % % See also getParameter % get indices of last matching name name = matlab.net.internal.getString(name, mfilename, 'NAME'); if name=='' error(message('MATLAB:http:ArgMustBeString', 'NAME')); end index = find(lower(obj.Parameters(:,1)) == lower(string(name)), 1, 'last'); if isempty(value) || (isstring(value) && isscalar(value) && value == '') obj.Parameters(index, :) = []; else % this might throw if name has bad syntax param = createParam(name, value, false); if isempty(index) % add param to end obj.Parameters(end+1, :) = param; else % set the last matching one to value obj.Parameters(index, :) = param; end end matlab.net.http.internal.nargoutWarning(nargout,mfilename,'setParameter'); end function str = string(obj) % string Return the value of a MediaType vector as a string % STR = string(MEDIATYPE) returns the value of the MEDIATYPE as it would % appear in an HTTP header. If input is a vector of MediaType, the strings % are comma-separated as they would appear in a header. if isscalar(obj) if isempty(obj.Subtype) || obj.Subtype == '' str = obj.Type; else if isempty(obj.Type) str = '/' + obj.Subtype; else str = obj.Type + '/' + obj.Subtype; end end params = getParamString(obj.Parameters); if ~isempty(params) if isempty(str) str = params; else str = str + '; ' + params; end end if isempty(str) str = string(''); end else members = arrayfun(@string, obj, 'UniformOutput', false); str = join([members{:}], ', '); end end function str = char(obj) % char Return the value of this MediaType vector as a character vector % For details see string. % % See also string str = char(string(obj)); end function mediaType = get.MediaInfo(obj) qIndex = find(lower(obj.Parameters(:,1)) == string('q'), 1); if ~isempty(qIndex) obj.Parameters(qIndex:end,:) = []; end mediaType = obj; end function weight = get.Weight(obj) weight = obj.getParameter('q'); if ~isempty(weight) weight = str2double(weight); end end function obj = set.Weight(obj, weight) weight = matlab.net.http.HeaderField.qualityToString(weight); obj = obj.setParameter('q',weight); end function obj = set.Type(obj, value) obj.Type = matlab.net.internal.getString(value, mfilename, 'Type'); end function obj = set.Subtype(obj, value) obj.Subtype = matlab.net.internal.getString(value, mfilename, 'Subtype'); end function tf = eq(obj, other) % eq, == Compare two MediaTypes % T1 == T2 does element by element comparisons between the MediaType arrays % T1 and T2 and returns a logical array of the same dimensions. If they % are not the same dimensions, one must be a scalar, and scalar-expansion % is used. % % Two MediaTypes are considered equal if they have the same type and % subtype using a case-insensitive comparison, and they have the same % parameters and values, where parameter names are case-insensitive and % values are case-sensitive, except for 'charset' values (as per RFC 2046, % <a href="http://tools.ietf.org/html/rfc2046#section-4.1.2">section 4.1.2</a>). Order of parameters is not significant. if size(obj) == size(other) if ~strcmp(class(obj),class(other)) error(message('MATLAB:http:MustBeSameClass')); end if isscalar(obj) tf = (isempty(obj.Type) == isempty(other.Type)) && ... (isempty(obj.Subtype) == isempty(other.Subtype)); if ~tf, return, end tf1 = isempty(obj.Type) && isempty(other.Type); tf2 = isempty(obj.Subtype) && isempty(other.Type); tf = (tf1 || strcmpi(obj.Type,other.Type)) && ... (tf2 || strcmpi(obj.Subtype,other.Subtype)) && ... size(obj.Parameters,1) == size(other.Parameters,1); if ~tf, return, end % Type and Subtype match and they have the same number of % parameters; sort them for comparison p1 = sortParams(obj.Parameters); p2 = sortParams(other.Parameters); tf = false; for i = 1 : size(p1,1) if ~strcmp(p1(i,1),p2(i,1)), return, end; % names different % names the same; do case-sensitive comparison of values % except for charset if strcmp(p1(i,1),'charset') tf = strcmpi(p1(i,2), p2(i,2)); else tf = strcmp(p1(i,2), p2(i,2)); end if ~tf, return, end end tf = true; else % Both args not scalars but sizes same, return array tf = arrayfun(@(a,b) a == b, obj, other); end elseif isscalar(other) % obj is array or []; scalar expansion of other % returns [] if obj is [] tf = arrayfun(@(a) a == other, obj); elseif isscalar(obj) % other is array or []; scalar expansion of obj % returns [] if other is [] tf = arrayfun(@(b) obj == b, other); else % neither is scalar or [] and dimension sizes differ error(message('MATLAB:dimagree')); end function pout = sortParams(p) % lowercase parameter names and sort them p(:,1) = lower(p(:,1)); pout = sortrows(p); end end function tf = isequal(obj, other) % isequal Compare two MediaType arrays % TF = isequal(T1,T2) returns true if T1 and T2 are MediaType arrays with % the same dimentions and corresponding elements compare equal according to % eq. % % See also eq. tf = isequal(size(obj), size(other)) && all(eq(obj, other)); end end methods (Access=protected) function group = getPropertyGroups(obj) % Provide a custom display that displays the Parameters array as an Mx2 % matrix of strings on one line and stringifies the MediaInfo field. group = getPropertyGroups@matlab.mixin.CustomDisplay(obj); if isscalar(obj) formatPair = @(n,v) '"' + n + '" "' + v + '"'; params = group.PropertyList.Parameters; pairs = arrayfun(formatPair, params(:,1), params(:,2), 'UniformOutput', false); if ~isempty(pairs) group.PropertyList.Parameters = '[' + strjoin([pairs{:}], '; ') + ']'; end if ~isempty(group.PropertyList.MediaInfo) group.PropertyList.MediaInfo = string(group.PropertyList.MediaInfo); end names = fieldnames(group.PropertyList); for i = 1 : length(names) name = names{i}; if isempty(group.PropertyList.(name)) group.PropertyList.(name) = []; end end end end end end function value = getValue(name,value,silent) % Return a string version of the value; throw mentioning name if not convertible try value = string(value); if ~isstring(value) || ~isscalar(value) if silent value = string(''); else throw(MException('MATLAB:http:CannotConvertValueToString', char(name))); end end catch if silent if ~isstring(value) value = string(''); end else error(message(... 'MATLAB:http:CannotConvertValueToString', char(name))); end end end function name = getName(name) % Return the name as a string; returns [] on error if (isstring(name) && isscalar(name) && name~='') || ... (ischar(name) && isvector(name)) name = getToken(name); else name = []; end end function param = createParam(name, value, silent) % Return a 2-element name,value vector. Return string('') if name isn't a string. % Throw mentioning name if value is invalid unless silent is set try name = getName(name); catch e if ~silent rethrow(e) else if ~isstring(name) name = []; end end end if isempty(name) param(1) = string(''); else param(1) = name; end param(2) = getValue(name, value, silent); end function token = getToken(str) % Verify syntax of token and return string. Throw on error. charName = char(str); % Look for any characters not allowed in a token as per RFC 7230, 3.2.6 ic = regexp(charName, '[^' + matlab.net.http.HeaderField.TokenChars + ']', 'once'); if isempty(ic) token = string(str); else error(message('MATLAB:http:IllegalCharInToken', charName(ic), charName)); end end function [type, subtype] = getTypeAndSubtype(str, silent) % Parse the type/subtype string for the MediaType % silent says don't throw error if syntax is invalid; instead include entire str % in type persistent token if isempty(token) % type and subtype are defined in RFC 7231, section 3.1.1.1 as tokens. token = '[' + matlab.net.http.HeaderField.TokenChars + ']+'; end res = regexp(str, '^(?<type>(??@token))/(?<subtype>(??@token))$', 'names'); if isempty(res) if silent res = struct('type',str,'subtype',''); else % on error, re-parse allowing any characters in type and subtype except / res = regexp(str, '^(?<type>[^/]+)/(?<subtype>[^/]+)$', 'names'); if ~isempty(res) % if it matches the type/subtype syntax, error must be due to illegal % character in token, so try both to issue bad char error getToken(res.type); getToken(res.subtype); else % not type/subtype syntax, so issue general error error(message('MATLAB:http:BadMediaType', char(str))); end end end type = string(res.type); subtype = string(res.subtype); end function str = getParamString(params) if isempty(params) str = []; else values = arrayfun(@matlab.net.http.internal.quoteToken, ... params(:,2), 'UniformOutput',false); params(:,2) = [values{:}]; str = join(join(params,'=',2),'; '); end end