applyConstraints method
Applies constraint annotations declared on a field or parameter.
Implementation
String applyConstraints(String schema, Element declaration, DartType type) {
var output = schema;
final isNumeric =
type is InterfaceType &&
(_core(type, 'int') || _core(type, 'double') || _core(type, 'num'));
final isString = type is InterfaceType && _core(type, 'String');
final isCollection =
type is InterfaceType && (type.isDartCoreList || type.isDartCoreSet);
final isSet = type is InterfaceType && type.isDartCoreSet;
final setConstraints = <String>[];
var hasUniqueConstraint = false;
for (final metadata in declaration.metadata.annotations) {
final value = metadata.computeConstantValue();
final valueType = value?.type;
if (value == null || valueType == null) continue;
if (_min.isExactlyType(valueType)) {
_require(declaration, type, '@Min', isNumeric, '@MinLength');
output = '$output.min(${_number(value, 'value')})';
} else if (_max.isExactlyType(valueType)) {
_require(declaration, type, '@Max', isNumeric, '@MaxLength');
output = '$output.max(${_number(value, 'value')})';
} else if (_multipleOf.isExactlyType(valueType)) {
_require(declaration, type, '@MultipleOf', isNumeric, 'numeric field');
output = '$output.multipleOf(${_number(value, 'value')})';
} else if (_positive.isExactlyType(valueType)) {
_require(declaration, type, '@Positive', isNumeric, 'numeric field');
output = '$output.positive()';
} else if (_negative.isExactlyType(valueType)) {
_require(declaration, type, '@Negative', isNumeric, 'numeric field');
output = '$output.negative()';
} else if (_minLength.isExactlyType(valueType)) {
_require(declaration, type, '@MinLength', isString, '@Min');
output = '$output.minLength(${value.getField('length')!.toIntValue()})';
} else if (_maxLength.isExactlyType(valueType)) {
_require(declaration, type, '@MaxLength', isString, '@Max');
output = '$output.maxLength(${value.getField('length')!.toIntValue()})';
} else if (_pattern.isExactlyType(valueType)) {
_require(declaration, type, '@Pattern', isString, 'String field');
output =
'$output.matches(${dartStringLiteral(value.getField('pattern')!.toStringValue()!)})';
} else if (_email.isExactlyType(valueType)) {
_require(declaration, type, '@Email', isString, 'String field');
output = '$output.email()';
} else if (_url.isExactlyType(valueType)) {
_require(declaration, type, '@Url', isString, 'String field');
output = '$output.url()';
} else if (_uri.isExactlyType(valueType)) {
_require(declaration, type, '@Uri', isString, 'String field');
output = '$output.uri()';
} else if (_uuid.isExactlyType(valueType)) {
_require(declaration, type, '@Uuid', isString, 'String field');
output = '$output.uuid()';
} else if (_date.isExactlyType(valueType)) {
_require(declaration, type, '@Date', isString, 'String field');
output = '$output.date()';
} else if (_dateTime.isExactlyType(valueType)) {
_require(declaration, type, '@DateTime', isString, 'String field');
output = '$output.datetime()';
} else if (_notEmpty.isExactlyType(valueType)) {
_require(declaration, type, '@NotEmpty', isString, 'String field');
output = '$output.notEmpty()';
} else if (_minItems.isExactlyType(valueType)) {
_require(
declaration,
type,
'@MinItems',
isCollection,
'List or Set field',
);
final constraint =
'.minItems(${value.getField('count')!.toIntValue()})';
if (isSet) {
setConstraints.add(constraint);
} else {
output = '$output$constraint';
}
} else if (_maxItems.isExactlyType(valueType)) {
_require(
declaration,
type,
'@MaxItems',
isCollection,
'List or Set field',
);
final constraint =
'.maxItems(${value.getField('count')!.toIntValue()})';
if (isSet) {
setConstraints.add(constraint);
} else {
output = '$output$constraint';
}
} else if (_uniqueItems.isExactlyType(valueType)) {
_require(
declaration,
type,
'@UniqueItems',
isCollection,
'List or Set field',
);
if (isSet) {
hasUniqueConstraint = true;
setConstraints.add('.unique()');
} else {
output = '$output.unique()';
}
}
}
if (setConstraints.isNotEmpty) {
if (isSet && !hasUniqueConstraint) {
// A Set cannot retain duplicate values after decoding. Validate the
// boundary with the same cardinality before the codec runs.
setConstraints.add('.unique()');
}
final codec = output.lastIndexOf('.codec<');
output = codec < 0
? '$output${setConstraints.join()}'
: '${output.substring(0, codec)}${setConstraints.join()}'
'${output.substring(codec)}';
}
return output;
}