NAME
Venus::Assert - Assert Class
ABSTRACT
Assert Class for Perl 5
SYNOPSIS
package main;
use Venus::Assert;
my $assert = Venus::Assert->new('Example');
# $assert->format(float => sub {sprintf('%.2f', $_->value)});
# $assert->accept(float => sub {$_->value > 1});
# $assert->check;DESCRIPTION
This package provides a mechanism for asserting type constraints and coercions on data.
ATTRIBUTES
This package has the following attributes:
expects
expects(ArrayRef)This attribute is read-write, accepts (ArrayRef) values, and is optional.
message
message(Str)This attribute is read-write, accepts (Str) values, and is optional.
name
name(Str)This attribute is read-write, accepts (Str) values, and is optional.
INHERITS
This package inherits behaviors from:
INTEGRATES
This package integrates behaviors from:
METHODS
This package provides the following methods:
accept
accept(Str $name, Any @args) (Object)The accept method registers a constraint based on the built-in type or package name provided as the first argument. The built-in types are "array", "boolean", "code", "float", "hash", "number", "object", "regexp", "scalar", "string", or "undef". Any name given that is not a built-in type is assumed to be a method (i.e. a method call) or an "object" of the name provided. Additional arguments are assumed to be arguments for the dispatched method call. Optionally, you can provide a callback to further constrain/validate the provided value, returning truthy or falsy, for methods that support it.
Since 1.40
- accept example 1
- 
# given: synopsis package main; $assert = $assert->accept('float'); # bless(..., "Venus::Assert") # ... # $assert->check; # 0 # $assert->check(1.01); # 1
- accept example 2
- 
# given: synopsis package main; $assert = $assert->accept('number'); # bless(..., "Venus::Assert") # ... # $assert->check(1.01); # 0 # $assert->check(1_01); # 1
- accept example 3
- 
# given: synopsis package Example1; sub new { bless {}; } package Example2; sub new { bless {}; } package main; $assert = $assert->accept('object'); # bless(..., "Venus::Assert") # ... # $assert->check; # 0 # $assert->check(qr//); # 0 # $assert->check(Example1->new); # 1 # $assert->check(Example2->new); # 1
- accept example 4
- 
# given: synopsis package Example1; sub new { bless {}; } package Example2; sub new { bless {}; } package main; $assert = $assert->accept('Example1'); # bless(..., "Venus::Assert") # ... # $assert->check; # 0 # $assert->check(qr//); # 0 # $assert->check(Example1->new); # 1 # $assert->check(Example2->new); # 0
any
any() (Assert)The any method configures the object to accept any value and returns the invocant.
Since 1.40
array
array(CodeRef $check) (Assert)The array method configures the object to accept array references and returns the invocant.
Since 1.40
- array example 1
- 
# given: synopsis package main; $assert = $assert->array; # $assert->check([]); # true
arrayref
arrayref(CodeRef $check) (Assert)The arrayref method configures the object to accept array references and returns the invocant.
Since 1.71
- arrayref example 1
- 
# given: synopsis package main; $assert = $assert->arrayref; # $assert->check([]); # true
attributes
attributes(Str | ArrayRef[Str] @pairs) (Assert)The attributes method configures the object to accept objects containing attributes whose values' match the attribute names and types specified, and returns the invocant.
Since 2.01
- attributes example 1
- 
# given: synopsis package main; $assert = $assert->attributes; # $assert->check(Venus::Assert->new); # true
- attributes example 2
- 
# given: synopsis package main; $assert = $assert->attributes(name => 'string'); # $assert->check(bless{}); # false # $assert->check(Venus::Assert->new); # true
- attributes example 3
- 
# given: synopsis package Example3; use Venus::Class; attr 'name'; package main; $assert = $assert->attributes(name => 'string', message => 'string'); # $assert->check(bless{}); # false # $assert->check(Venus::Assert->new); # true # $assert->check(Example3->new); # false
boolean
boolean(CodeRef $check) (Assert)The boolean method configures the object to accept boolean values and returns the invocant.
Since 1.40
- boolean example 1
- 
# given: synopsis package main; $assert = $assert->boolean; # $assert->check(false); # true
check
check(Any $data) (Bool)The check method returns true or false if the data provided passes the registered constraints.
Since 1.23
- check example 1
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $check = $assert->check; # 0
- check example 2
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $check = $assert->check('0.01'); # 0
- check example 3
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $check = $assert->check('1.01'); # 1
- check example 4
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $check = $assert->check(time); # 0
checker
checker(Str $expr) (CodeRef)The checker method calls "expression" with the type assertion signature provided and returns a coderef which calls the "check" method when called.
Since 2.32
- checker example 1
- 
# given: synopsis package main; my $checker = $assert->checker('string'); # sub { ... } # $checker->('hello'); # true # $checker->(['goodbye']); # false
clear
clear() (Assert)The clear method resets all match conditions for both constraints and coercions and returns the invocant.
Since 1.40
- clear example 1
- 
# given: synopsis package main; $assert = $assert->clear; # bless(..., "Venus::Assert")
code
code(CodeRef $check) (Assert)The code method configures the object to accept code references and returns the invocant.
Since 1.40
- code example 1
- 
# given: synopsis package main; $assert = $assert->code; # $assert->check(sub{}); # true
coderef
coderef(CodeRef $check) (Assert)The coderef method configures the object to accept code references and returns the invocant.
Since 1.71
- coderef example 1
- 
# given: synopsis package main; $assert = $assert->coderef; # $assert->check(sub{}); # true
coerce
coerce(Any $data) (Any)The coerce method returns the coerced data if the data provided matches any of the registered coercions.
Since 1.23
- coerce example 1
- 
# given: synopsis package main; $assert->coercion(float => sub { sprintf('%.2f', $_->value) }); my $coerce = $assert->coerce; # undef
- coerce example 2
- 
# given: synopsis package main; $assert->coercion(float => sub { sprintf('%.2f', $_->value) }); my $coerce = $assert->coerce('1.01'); # "1.01"
- coerce example 3
- 
# given: synopsis package main; $assert->coercion(float => sub { sprintf('%.2f', $_->value) }); my $coerce = $assert->coerce('1.00001'); # "1.00"
- coerce example 4
- 
# given: synopsis package main; $assert->coercion(float => sub { sprintf('%.2f', $_->value) }); my $coerce = $assert->coerce('hello world'); # "hello world"
coercion
coercion(Str $type, CodeRef $code) (Object)The coercion method registers a coercion based on the type provided.
Since 1.23
- coercion example 1
- 
# given: synopsis package main; $assert = $assert->coercion(float => sub { sprintf('%.2f', $_->value) }); # bless(..., "Venus::Assert")
coercions
coercions() (Match)The coercions method returns the registered coercions as a Venus::Match object.
Since 1.23
- coercions example 1
- 
# given: synopsis package main; my $coercions = $assert->coercions; # bless(..., "Venus::Match")
conditions
conditions() (Assert)The conditions method is an object construction hook that allows subclasses to configure the object on construction setting up constraints and coercions and returning the invocant.
Since 1.40
- conditions example 2
- 
package Example::Type::PositveNumber; use base 'Venus::Assert'; sub conditions { my ($self) = @_; $self->number(sub { $_->value >= 0 }); return $self; } package main; my $assert = Example::Type::PositveNumber->new; # $assert->check(0); # true # $assert->check(1); # true # $assert->check(-1); # false
constraint
constraint(Str $type, CodeRef $code) (Object)The constraint method registers a constraint based on the type provided.
Since 1.23
- constraint example 1
- 
# given: synopsis package main; $assert = $assert->constraint(float => sub { $_->value > 1 }); # bless(..., "Venus::Assert")
constraints
constraints() (Match)The constraints method returns the registered constraints as a Venus::Match object.
Since 1.23
- constraints example 1
- 
# given: synopsis package main; my $constraints = $assert->constraints; # bless(..., "Venus::Match")
defined
defined(CodeRef $check) (Assert)The defined method configures the object to accept any value that's not undefined and returns the invocant.
Since 1.40
- defined example 1
- 
# given: synopsis package main; $assert = $assert->defined; # $assert->check(0); # true
either
either(Str | ArrayRef[Str|ArrayRef] $dispatch) (Assert)The either method configures the object to accept "either" of the conditions provided, which may be a string or arrayref representing a method call, and returns the invocant.
Since 2.01
- either example 1
- 
# given: synopsis package main; $assert = $assert->either('string'); # $assert->check('1'); # true # $assert->check(1); # false
- either example 2
- 
# given: synopsis package main; $assert = $assert->either('string', 'number'); # $assert->check(true); # false # $assert->check('1'); # true # $assert->check(1); # true
- either example 3
- 
# given: synopsis package main; $assert = $assert->either('number', 'boolean'); # $assert->check(true); # true # $assert->check('1'); # false # $assert->check(1); # true
enum
enum(Any @data) (Assert)The enum method configures the object to accept any one of the provide options, and returns the invocant.
Since 1.40
- enum example 1
- 
# given: synopsis package main; $assert = $assert->enum('s', 'm', 'l', 'xl'); # $assert->check('s'); # true # $assert->check('xs'); # false
expression
expression(Str $expr) (Assert)The expression method parses a string representation of an type assertion signature, registers the subexpressions using the "either" and "accept" methods, and returns the invocant.
Since 1.71
- expression example 1
- 
# given: synopsis package main; $assert = $assert->expression('string'); # $assert->check('hello'); # true # $assert->check(['goodbye']); # false
- expression example 2
- 
# given: synopsis package main; $assert = $assert->expression('string | coderef'); # $assert->check('hello'); # true # $assert->check(sub{'hello'}); # true # $assert->check(['goodbye']); # false
- expression example 3
- 
# given: synopsis package main; $assert = $assert->expression('string | coderef | Venus::Assert'); # $assert->check('hello'); # true # $assert->check(sub{'hello'}); # true # $assert->check($assert); # true # $assert->check(['goodbye']); # false
- expression example 4
- 
# given: synopsis package main; $assert = $assert->expression('Venus::Assert | within[arrayref, Venus::Assert]'); # $assert->check('hello'); # false # $assert->check(sub{'hello'}); # false # $assert->check($assert); # true # $assert->check(['goodbye']); # false # $assert->check([$assert]); # true
- expression example 5
- 
# given: synopsis package main; $assert = $assert->expression(' string | within[ arrayref, within[ hashref, string ] ] '); # $assert->check('hello'); # true # $assert->check(sub{'hello'}); # false # $assert->check($assert); # false # $assert->check([]); # false # $assert->check([{'test' => ['okay']}]); # false # $assert->check([{'test' => 'okay'}]); # true
float
float(CodeRef $check) (Assert)The float method configures the object to accept floating-point values and returns the invocant.
Since 1.40
- float example 1
- 
# given: synopsis package main; $assert = $assert->float; # $assert->check(1.23); # true
format
format(Str $name, CodeRef $callback) (Object)The format method registers a coercion based on the built-in type or package name and callback provided. The built-in types are "array", "boolean", "code", "float", "hash", "number", "object", "regexp", "scalar", "string", or "undef". Any name given that is not a built-in type is assumed to be an "object" of the name provided.
Since 1.40
- format example 1
- 
# given: synopsis package main; $assert = $assert->format('float', sub{int $_->value}); # bless(..., "Venus::Assert") # ... # $assert->coerce; # undef # $assert->coerce(1.01); # 1
- format example 2
- 
# given: synopsis package main; $assert = $assert->format('number', sub{ sprintf('%.2f', $_->value) }); # bless(..., "Venus::Assert") # ... # $assert->coerce(1.01); # 1.01 # $assert->coerce(1_01); # 101.00
- format example 3
- 
# given: synopsis package Example1; sub new { bless {}; } package Example2; sub new { bless {}; } package main; $assert = $assert->format('object', sub{ ref $_->value }); # bless(..., "Venus::Assert") # ... # $assert->coerce(qr//); # qr// # $assert->coerce(Example1->new); # "Example1" # $assert->coerce(Example2->new); # "Example2"
- format example 4
- 
# given: synopsis package Example1; sub new { bless {}; } package Example2; sub new { bless {}; } package main; $assert = $assert->format('Example1', sub{ ref $_->value }); # bless(..., "Venus::Assert") # ... # $assert->coerce(qr//); # qr// # $assert->coerce(Example1->new); # "Example1" # $assert->coerce(Example2->new); # bless({}, "Example2")
hash
hash(CodeRef $check) (Assert)The hash method configures the object to accept hash references and returns the invocant.
Since 1.40
- hash example 1
- 
# given: synopsis package main; $assert = $assert->hash; # $assert->check({}); # true
hashkeys
hashkeys(Str | ArrayRef[Str] @pairs) (Assert)The hashkeys method configures the object to accept hash based values containing the keys whose values' match the specified types, and returns the invocant.
Since 2.01
- hashkeys example 1
- 
# given: synopsis package main; $assert = $assert->hashkeys; # $assert->check({}); # false # $assert->check({random => rand}); # true
- hashkeys example 2
- 
# given: synopsis package main; $assert = $assert->hashkeys(random => 'float'); # $assert->check({}); # false # $assert->check({random => rand}); # true # $assert->check({random => time}); # false
- hashkeys example 3
- 
# given: synopsis package main; $assert = $assert->hashkeys(random => ['either', 'float', 'number']); # $assert->check({}); # false # $assert->check({random => rand}); # true # $assert->check({random => time}); # true # $assert->check({random => 'okay'}); # false # $assert->check(bless{random => rand}); # true # $assert->check(bless{random => time}); # true # $assert->check(bless{random => 'okay'}); # false
hashref
hashref(CodeRef $check) (Assert)The hashref method configures the object to accept hash references and returns the invocant.
Since 1.71
- hashref example 1
- 
# given: synopsis package main; $assert = $assert->hashref; # $assert->check({}); # true
identity
identity(Str $name) (Assert)The identity method configures the object to accept objects of the type specified as the argument, and returns the invocant.
Since 1.40
- identity example 1
- 
# given: synopsis package main; $assert = $assert->identity('Venus::Assert'); # $assert->check(Venus::Assert->new); # true
inherits
inherits(Str $name) (Assert)The inherits method configures the object to accept objects of the type specified as the argument, and returns the invocant. This method is a proxy for the "identity" method.
Since 2.01
- inherits example 1
- 
# given: synopsis package main; $assert = $assert->inherits('Venus::Assert'); # $assert->check(Venus::Assert->new); # true
integrates
integrates(Str $name) (Assert)The integrates method configures the object to accept objects that support the "does" behavior and consumes the "role" specified as the argument, and returns the invocant.
Since 2.01
- integrates example 1
- 
# given: synopsis package main; $assert = $assert->integrates('Venus::Role::Doable'); # $assert->check(Venus::Assert->new); # true
maybe
maybe(Str $type, Any @args) (Assert)The maybe method configures the object to accept the type provided as an argument, or undef, and returns the invocant.
Since 1.40
- maybe example 1
- 
# given: synopsis package main; $assert = $assert->maybe('code'); # $assert->check(sub{}); # true # $assert->check(undef); # true
number
number(CodeRef $check) (Assert)The number method configures the object to accept numberic values and returns the invocant.
Since 1.40
- number example 1
- 
# given: synopsis package main; $assert = $assert->number; # $assert->check(0); # true
object
object(CodeRef $check) (Assert)The object method configures the object to accept objects and returns the invocant.
Since 1.40
- object example 1
- 
# given: synopsis package main; $assert = $assert->object; # $assert->check(bless{}); # true
package
package() (Assert)The package method configures the object to accept package names (which are loaded) and returns the invocant.
Since 1.40
- package example 1
- 
# given: synopsis package main; $assert = $assert->package; # $assert->check('Venus'); # true
parse
parse(Str $expr) (Any)The parse method accepts a string representation of a type assertion signature and returns a data structure representing one or more method calls to be used for validating the assertion signature.
Since 2.01
- parse example 3
- 
# given: synopsis package main; my $parsed = $assert->parse('string | number'); # ['either', 'string', 'number']
- parse example 4
- 
# given: synopsis package main; my $parsed = $assert->parse('enum[up,down,left,right]'); # [['enum', 'up', 'down', 'left', 'right']]
- parse example 5
- 
# given: synopsis package main; my $parsed = $assert->parse('number | float | boolean'); # ['either', 'number', 'float', 'boolean']
- parse example 6
- 
# given: synopsis package main; my $parsed = $assert->parse('Example'); # ['Example']
- parse example 7
- 
# given: synopsis package main; my $parsed = $assert->parse('coderef | Venus::Code'); # ['either', 'coderef', 'Venus::Code']
- parse example 8
- 
# given: synopsis package main; my $parsed = $assert->parse('tuple[number, arrayref, coderef]'); # [['tuple', 'number', 'arrayref', 'coderef']]
- parse example 9
- 
# given: synopsis package main; my $parsed = $assert->parse('tuple[number, within[arrayref, hashref], coderef]'); # [['tuple', 'number', ['within', 'arrayref', 'hashref'], 'coderef']]
- parse example 10
- 
# given: synopsis package main; my $parsed = $assert->parse( 'tuple[number, within[arrayref, hashref] | arrayref, coderef]' ); # [ # ['tuple', 'number', # ['either', ['within', 'arrayref', 'hashref'], 'arrayref'], 'coderef'] # ]
- parse example 11
- 
# given: synopsis package main; my $parsed = $assert->parse( 'hashkeys["id", number | float, "upvotes", within[arrayref, boolean]]' ); # [[ # 'hashkeys', # 'id', # ['either', 'number', 'float'], # 'upvotes', # ['within', 'arrayref', 'boolean'] # ]]
reference
reference(CodeRef $check) (Assert)The reference method configures the object to accept references and returns the invocant.
Since 1.40
- reference example 1
- 
# given: synopsis package main; $assert = $assert->reference; # $assert->check(sub{}); # true
regexp
regexp(CodeRef $check) (Assert)The regexp method configures the object to accept regular expression objects and returns the invocant.
Since 1.40
- regexp example 1
- 
# given: synopsis package main; $assert = $assert->regexp; # $assert->check(qr//); # true
render
render(Str $into, Str $expression) (Str)The render method builds and returns a type expressions suitable for providing to "expression" based on the data provided.
Since 2.55
- render example 2
- 
# given: synopsis package main; $assert = $assert->render(undef, 'string'); # "string"
- render example 3
- 
# given: synopsis package main; $assert = $assert->render('routines', ['say', 'say_pretty']); # 'routines["say", "say_pretty"]'
- render example 4
- 
# given: synopsis package main; $assert = $assert->render('hashkeys', {id => 'number', name => 'string'}); # 'hashkeys["id", number, "name", string]'
- render example 5
- 
# given: synopsis package main; $assert = $assert->render('hashkeys', { id => 'number', profile => { level => 'string', }, }); # 'hashkeys["id", number, "profile", hashkeys["level", string]]'
routines
routines(Str @names) (Assert)The routines method configures the object to accept an object having all of the routines provided, and returns the invocant.
Since 1.40
- routines example 1
- 
# given: synopsis package main; $assert = $assert->routines('new', 'print', 'say'); # $assert->check(Venus::Assert->new); # true
scalar
scalar(CodeRef $check) (Assert)The scalar method configures the object to accept scalar references and returns the invocant.
Since 1.40
- scalar example 1
- 
# given: synopsis package main; $assert = $assert->scalar; # $assert->check(\1); # true
scalarref
scalarref(CodeRef $check) (Assert)The scalarref method configures the object to accept scalar references and returns the invocant.
Since 1.71
- scalarref example 1
- 
# given: synopsis package main; $assert = $assert->scalarref; # $assert->check(\1); # true
string
string(CodeRef $check) (Assert)The string method configures the object to accept string values and returns the invocant.
Since 1.40
- string example 1
- 
# given: synopsis package main; $assert = $assert->string; # $assert->check(''); # true
tuple
tuple(Str | ArrayRef[Str] @types) (Assert)The tuple method configures the object to accept array references which conform to a tuple specification, and returns the invocant. The value being evaluated must contain at-least one element to match.
Since 1.40
- tuple example 1
- 
# given: synopsis package main; $assert = $assert->tuple('number', ['maybe', 'array'], 'code'); # $assert->check([200, [], sub{}]); # true
undef
undef(CodeRef $check) (Assert)The undef method configures the object to accept undefined values and returns the invocant.
Since 1.40
- undef example 1
- 
# given: synopsis package main; $assert = $assert->undef; # $assert->check(undef); # true
validate
validate(Any $data) (Any)The validate method returns the data provided if the data provided passes the registered constraints, or throws an exception.
Since 1.23
- validate example 1
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $result = $assert->validate; # Exception! (isa Venus::Assert::Error) (see error_on_validate)
- validate example 2
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $result = $assert->validate('0.01'); # Exception! (isa Venus::Assert::Error) (see error_on_validate)
- validate example 3
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $result = $assert->validate('1.01'); # "1.01"
- validate example 4
- 
# given: synopsis package main; $assert->constraint(float => sub { $_->value > 1 }); my $result = $assert->validate(time); # Exception! (isa Venus::Assert::Error) (see error_on_validate)
validator
validator(Str $expr) (CodeRef)The validator method returns a coderef that can be used as a value validator, which returns the data provided if the data provided passes the registered constraints, or throws an exception.
Since 1.40
- validator example 1
- 
# given: synopsis package main; my $validator = $assert->validator('string'); # sub { ... } # $validator->('hello'); # "hello" # $validator->(['goodbye']); # Exception! (isa Venus::Error) (see error_on_validate)
value
value(CodeRef $check) (Assert)The value method configures the object to accept defined, non-reference, values, and returns the invocant.
Since 1.40
- value example 1
- 
# given: synopsis package main; $assert = $assert->value; # $assert->check(1_000_000); # true
within
within(Str $type) (Assert)The within method configures the object, registering a constraint action as a sub-match operation, to accept array or hash based values, and returns a Venus::Assert instance for the sub-match operation (not the invocant). This operation can traverse blessed array or hash based values. The value being evaluated must contain at-least one element to match.
Since 1.40
- within example 1
- 
# given: synopsis package main; my $within = $assert->within('array')->code; my $action = $assert; # $assert->check([]); # false # $assert->check([sub{}]); # true # $assert->check([{}]); # false # $assert->check(bless[]); # false # $assert->check(bless[sub{}]); # true
- within example 2
- 
# given: synopsis package main; my $within = $assert->within('hash')->code; my $action = $assert; # $assert->check({}); # false # $assert->check({test => sub{}}); # true # $assert->check({test => {}}); # false # $assert->check({test => bless{}}); # false # $assert->check({test => bless sub{}}); # false
- within example 3
- 
# given: synopsis package main; my $within = $assert->within('hashref', 'code'); my $action = $assert; # $assert->check({}); # false # $assert->check({test => sub{}}); # true # $assert->check({test => {}}); # false # $assert->check({test => bless{}}); # false # $assert->check({test => bless sub{}}); # false
yesno
yesno(CodeRef $check) (Assert)The yesno method configures the object to accept a string value that's either "yes" or 1, "no" or 0, and returns the invocant.
Since 2.01
- yesno example 1
- 
# given: synopsis package main; $assert = $assert->yesno; # $assert->check(undef); # false # $assert->check(0); # true # $assert->check('No'); # true # $assert->check('n'); # true # $assert->check(1); # true # $assert->check('Yes'); # true # $assert->check('y'); # true # $assert->check('Okay'); # false
ERRORS
This package may raise the following errors:
- error: error_on_validate
- 
This package may raise an error_on_validate exception. example 1 # given: synopsis; my @args = ("..."); my $error = $assert->throw('error_on_validate', @args)->catch('error'); # my $name = $error->name; # "on_validate" # my $message = $error->message; # "..." # my $identity = $error->stash('identity'); # "string"
- error: error_on_within
- 
This package may raise an error_on_within exception. example 1 # given: synopsis; my @args = ('coderef', 'string'); my $error = $assert->throw('error_on_within', @args)->catch('error'); # my $ = $error->name; # "on_within" # my $message = $error->message; # "Invalid type (\"$type\") palid ed to the \"within\" method" # my $self = $error->stash('self'); # $assert # my $type = $error->stash('type' # "coderef" # my $args = $error->stash('args'); # ["string"]
AUTHORS
Awncorp, awncorp@cpan.org
LICENSE
Copyright (C) 2000, Al Newkirk.
This program is free software, you can redistribute it and/or modify it under the terms of the Apache license version 2.0.