# (c) 2004 by Murat Uenalan. All rights reserved. Note: This program is
# free software; you can redistribute it and/or modify it under the same
# terms as perl itself
use strict;
package Data::Type::Collection::Std::Interface;
our @ISA = qw(Data::Type::Object::Interface);
our $VERSION = '0.01.25';
sub prefix : method {'Std::'}
sub pkg_prefix : method {'std_'}
package Data::Type::Collection::Std::Interface::Numeric;
our @ISA = qw(Data::Type::Collection::Std::Interface);
sub desc : method { 'Numeric' }
sub doc : method { q{Number or related} }
package Data::Type::Collection::Std::Interface::Temporal;
our @ISA = qw(Data::Type::Collection::Std::Interface);
sub desc { 'Time or Date' }
sub doc { 'Any time or date related object.' }
package Data::Type::Collection::Std::Interface::String;
our @ISA = qw(Data::Type::Collection::Std::Interface);
sub desc { 'String' }
sub doc { q{Something that may be matched with a regex and doesnt belong to another category.} }
package Data::Type::Collection::Std::Interface::Logic;
our @ISA = qw(Data::Type::Collection::Std::Interface);
sub desc { 'Logic' }
sub doc { 'Something that requires some more program logic.' }
package Data::Type::Collection::Std::Interface::Business;
our @ISA = qw(Data::Type::Collection::Std::Interface);
our $VERSION = '0.01.03';
sub desc { 'Business' }
sub doc { 'Something from the CPAN C<Business> namespace or simply business related.' }
package Data::Type::Collection::Std::Interface::Locale;
our @ISA = qw(Data::Type::Collection::Std::Interface);
our $VERSION = '0.01.05';
sub desc { 'Locale' }
sub doc { 'Language or Localization specific.' }
#
# Custom datatypes
#
package Data::Type::Object::std_word;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.25';
sub desc { 'word (without whitespaces)' }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::match( 'std/word' ) );
}
package Data::Type::Object::std_bool;
our @ISA = qw(Data::Type::Collection::Std::Interface::Numeric);
our $VERSION = '0.01.25';
sub desc : method { 'boolean value' }
sub info
{
my $this = shift;
return sprintf '%s value', $this->[0] || 'true or false';
}
sub _test
{
my $this = shift;
Data::Type::ok( $this->[0] eq 'true' ? 1 : 0, Data::Type::Facet::bool( $this->[0] ) );
}
package Data::Type::Object::std_int;
our @ISA = qw(Data::Type::Collection::Std::Interface::Numeric);
our $VERSION = '0.01.27';
sub _depends { qw(Regexp::Common) }
sub desc : method { 'integer' }
sub info { 'integer' }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::match( 'std/int' ) );
}
package Data::Type::Object::std_num;
our @ISA = qw(Data::Type::Collection::Std::Interface::Numeric);
our $VERSION = '0.01.25';
sub desc : method { 'number' }
sub info { 'number' }
sub _test
{
my $this = shift;
# Here we test the hierarchy feature -> nested types !
Data::Type::Object::std_int->test( $Data::Type::value );
}
package Data::Type::Object::std_real;
our @ISA = qw(Data::Type::Collection::Std::Interface::Numeric);
our $VERSION = '0.01.25';
sub _depends { qw(Regexp::Common) }
sub desc : method { 'real' }
sub info { 'real' }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::match( 'std/real' ) );
}
package Data::Type::Object::std_quoted;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.25';
sub _depends { qw(Regexp::Common) }
sub desc : method { 'quoted string' }
sub info { 'quoted string' }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::match( 'std/quoted' ) );
}
package Data::Type::Object::std_gender;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.25';
sub desc : method { 'human gender' }
sub info : method
{
my $this = shift;
return sprintf 'gender %s', join( ', ', $this->param );
}
sub param : method { qw(male female) }
sub choice : method
{
my $this = shift;
return $this->param;
}
sub _test : method
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::exists( [ $this->param ] ) );
}
package Data::Type::Object::std_gender_de;
our $VERSION = '0.01.12';
our @ISA = qw(Data::Type::Object::std_gender);
sub export { ('GENDER::DE') }
sub param : method { ( 'weiblich', 'männlich' ) }
package Data::Type::Object::std_yesno;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.25';
sub desc : method { 'primitiv answer' }
sub info : method
{
my $this = shift;
return sprintf q{a primitiv answer (%s)}, join( ', ', $this->param ) ;
}
sub param : method { qw(yes no) }
sub choice : method
{
my $this = shift;
return $this->param;
}
sub _filters : method { return ( [ 'chomp' ], [ 'lc' ] ) }
sub _test : method
{
my $this = shift;
# Data::Type->filter( [ 'chomp' ], [ 'lc' ] );
Data::Type::ok( 1, Data::Type::Facet::exists( [ $this->param ] ) );
}
package Data::Type::Object::std_yesno_de;
our @ISA = qw(Data::Type::Object::std_yesno);
our $VERSION = '0.01.14';
sub export { ('YESNO::DE') };
sub param { qw(ja nein) }
package Data::Type::Object::std_ref;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.25';
sub desc : method { 'perl reference' }
sub info
{
my $this = shift;
return qq{a reference to a variable};
}
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::ref( $Data::Type::value ) );
if( @$this )
{
$Data::Type::value = ref( $Data::Type::value );
$this = [ @$this ] unless ref( $this ) eq 'ARRAY';
Data::Type::ok( 1, Data::Type::Facet::exists( [ @$this ] ) );
}
}
package Data::Type::Object::std_creditcard;
our @ISA = qw(Data::Type::Collection::Std::Interface::Business);
our $VERSION = '0.01.25';
sub _depends { qw(Business::CreditCard) }
sub desc : method { 'creditcard' }
our $cardformats =
{
DINERS =>
{
name => 'Diners Club',
prefix => { 3000 => 3059, 3600 => 3699, 3800 => 3889 },
digits => [ 14 ],
},
AMEX =>
{
name => 'American Express',
prefix => { 3400 => 3499, 3700 => 3799 },
digits => [ 15 ],
},
JCB =>
{
name => 'JCB',
prefix => { 3528 => 3589 },
digits => [ 16 ],
},
BLACHE =>
{
name => 'Carte Blache',
prefix => { 3890 => 3899 },
digits => [ 14 ],
},
VISA =>
{
name => 'VISA',
prefix=> [ 4 ],
digits => [ 13, 16 ],
},
MASTERCARD =>
{
name => 'MasterCard',
prefix => { 5100 => 5599 },
digits => [ 16 ],
},
BANKCARD =>
{
name => 'Australian BankCard',
prefix => [ 5610 ],
digits => [ 16 ],
},
DISCOVER =>
{
name => 'Discover/Novus',
prefix => [ 6011 ],
digits => [ 16 ],
}
};
sub info
{
my $this = shift;
return sprintf 'is one of a set of creditcard type (%s)', join( ', ', keys %$cardformats );
}
sub usage
{
my $this = shift;
return sprintf "CREDITCARD( Set of [%s], .. )", join( '|', keys %$cardformats );
}
our $default_cc = 'VISA';
sub _filters : method { return ( [ 'strip', '\D' ] ) }
sub _test
{
my $this = shift;
printf "creditcard '%s' is about to be tested\n", $Data::Type::value if $Data::Type::debug;
Data::Type::ok( 1, Data::Type::Facet::mod10check( $Data::Type::value ) );
push @$this, $default_cc unless @$this;
my $results = {};
foreach ( @$this )
{
$results->{$_} = [];
my $card = $cardformats->{$_};
push @{ $results->{$_} }, 'digits' if map { length($Data::Type::value) eq $_ ? () : 'invalid' } @{ $card->{digits} };
if( ref $card->{prefix} eq 'HASH' )
{
my $prefix;
while( my( $min, $max ) = each %{ $card->{prefix} } )
{
$prefix = pack( 'a'.length($max), $Data::Type::value );
push @{ $results->{$_} }, 'prefix' if $prefix+0 > $max;
$prefix = pack( 'a'.length($min), $Data::Type::value );
push @{ $results->{$_} }, 'prefix' if $prefix+0 < $min;
}
}
elsif( ref $card->{prefix} eq 'ARRAY' )
{
for ( @{ $card->{prefix} } )
{
$_ .= '';
push @{ $results->{$_} }, 'prefix' unless $Data::Type::value =~ /$_/;
}
}
}
throw Data::Type::Exception( text => 'creditcard not valid' ) unless map { @{ $results->{$_} } == 0 ? 1 : () } keys %$results;
}
package Data::Type::Object::std_binary;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.25';
sub desc : method { 'binary code' }
sub info : method { q{binary code} }
sub usage : method { 'Set of ( [0|1] )' }
sub _test : method
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::match( 'std/binary' ) );
}
package Data::Type::Object::std_hex;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.25';
sub info : method { qq{hexadecimal code} }
sub usage { 'Set of ( ([0-9a-fA-F]) )' }
sub _filters : method { return ( [ 'strip', '\s' ] ) }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::match( 'std/hex' ) );
}
package Data::Type::Object::std_langcode;
our @ISA = qw(Data::Type::Collection::Std::Interface::Locale);
our $VERSION = '0.01.03';
sub _depends { qw(Locale::Language) }
sub desc : method { 'language code' }
sub export { ('LANGCODE') }
sub info
{
my $this = shift;
return qq{a Locale::Language language code};
}
sub usage { '' }
sub _filters : method { return ( [ 'strip', '\s' ], [ 'chomp' ], [ 'lc' ] ) }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::exists( [ Locale::Language::all_language_codes() ] ) );
}
package Data::Type::Object::std_langname;
our @ISA = qw(Data::Type::Collection::Std::Interface::Locale);
our $VERSION = '0.01.03';
sub _depends { qw(Locale::Language) }
sub desc : method { 'natural language' }
sub info : method { qq{a language name} }
sub _filters : method { return ( [ 'strip', '\s' ], [ 'chomp' ] ) }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::exists( [ Locale::Language::all_language_names() ] ) );
}
package Data::Type::Object::std_issn;
our @ISA = qw(Data::Type::Collection::Std::Interface::Business);
our $VERSION = '0.01.03';
sub _depends { qw(Business::ISSN) }
sub desc : method { 'ISSN' }
sub info { qq{an International Standard Serial Number} }
sub usage { 'example: 14565935' }
sub _filters : method { return ( [ 'strip', '\s' ], [ 'chomp' ] ) }
sub _test
{
my $this = shift;
throw Data::Type::Facet::Exception() unless new Business::ISSN( $Data::Type::value )->is_valid;
}
package Data::Type::Object::std_upc;
our @ISA = qw(Data::Type::Collection::Std::Interface::Business);
our $VERSION = '0.01.03';
sub _depends { qw(Business::UPC) }
sub desc : method { 'UPC' }
sub info { qq{standard (type-A) Universal Product Code} }
sub usage { 'i.e. 012345678905' }
sub _filters : method { return ( [ 'strip', '\s' ], [ 'chomp' ] ) }
sub _test
{
my $this = shift;
throw Data::Type::Facet::Exception() unless Business::UPC->new( $Data::Type::value )->is_valid;
}
package Data::Type::Object::std_cins;
our @ISA = qw(Data::Type::Collection::Std::Interface::Business);
our $VERSION = '0.01.03';
sub _depends { qw(Business::CINS) }
sub desc : method { 'CINS' }
sub info { qq{a CUSIP International Numbering System Number} }
sub usage { 'i.e. 035231AH2' }
sub _filters : method { return ( [ 'strip', '\s' ], [ 'chomp' ] ) }
sub _test
{
my $this = shift;
my $result = Business::CINS->new( $Data::Type::value )->error;
throw Data::Type::Facet::Exception( text => $result ) if defined $result;
}
package Data::Type::Object::std_defined;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.04';
sub desc : method { 'defined value' }
sub info { qq{a defined (not undef) value} }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::defined() );
}
package Data::Type::Object::std_email;
{
package Data::Type::Facet::__email;
our @ISA = qw(Data::Type::Facet::Interface);
our $VERSION = '0.01.25';
sub _depends : method { qw(Email::Valid) }
sub desc : method { 'valid email' }
sub info : method { 'valid email' }
sub test : method
{
my $this = shift;
my $result = Email::Valid->address( -address => $Data::Type::value, -mxcheck => $this->[0] || 0 );
throw Data::Type::Facet::Exception( text => 'not an email address' ) unless $result;
}
}
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.25';
sub _depends { qw(Email::Valid) }
sub desc : method { 'email address' }
sub usage : method
{
return <<'END_HERE';
[MXCHECK as STD::BOOL]
MXCHECK results actually tests the mx host via internet (see Email::Valid)
END_HERE
}
sub info
{
my $this = shift;
return sprintf "valid email address (%s mxcheck)", $this->[0] ? 'with' : 'without';
}
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::__email( $this->[0] ) );
}
package Data::Type::Object::std_uri;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.25';
sub _depends { qw(Regexp::Common) }
sub desc : method { 'uri' }
sub info
{
my $this = shift;
my $scheme = $this->[0] || 'http';
return sprintf '%s uri', $scheme;
}
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::match( 'std/uri', $this->[0] || 'http' ) );
}
package Data::Type::Object::std_ip;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.04';
sub _depends { qw(Regexp::Common Net::IPv6Addr) }
sub desc : method { 'IP (v4 or v6) or MAC network address' }
sub info { 'IP (V4, V6, MAC) network address' }
sub default { 'v4' }
sub _test
{
my $this = shift;
my $format = lc( $this->[0] || $this->default );
$format = 'IP'.$format if $format =~ /^[vV][46]$/;
if( $format =~ /6/ )
{
eval
{
new Net::IPv6Addr( $Data::Type::value );
};
throw Data::Type::Exception ( text => $@ ) if $@;
}
else
{
Data::Type::ok( 1, Data::Type::Facet::match( 'std/net', $format ) );
}
}
package Data::Type::Object::std_domain;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.04';
sub desc : method { 'domain name' }
sub info { qq{a network domain name} }
sub _filters : method { return ( [ 'lc' ] ) }
sub _test
{
my $this = shift;
Data::Type::ok( 1, Data::Type::Facet::defined() );
Data::Type::ok( 1, Data::Type::Facet::match( 'std/domain' ) );
}
package Data::Type::Object::std_port;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.04';
sub desc : method { 'tcp port number' }
sub info { qq{a network port number} }
sub _test
{
my $this = shift;
Data::Type::Object::std_int->test( $Data::Type::value );
throw Data::Type::Exception->new( text => 'no port number' ) unless $Data::Type::value < 650;
}
package Data::Type::Object::std_path;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.06';
sub export { ( 'PATH' ) }
sub desc : method { 'path' }
sub info { qq{a path string} }
sub _test
{
my $this = shift;
#Data::Type::ok( 0, Data::Type::Facet::match( qr/.+/ ) );
}
package Data::Type::Object::std_regionname;
our @ISA = qw(Data::Type::Collection::Std::Interface::Locale);
our $VERSION = '0.01.05';
sub export { ('REGIONNAME') }
sub _depends { qw(Locale::SubCountry) }
sub desc : method { 'country region' }
sub info : method { qq{region name} }
sub _filters : method { return ( [ 'uc' ] ) }
sub _test
{
my $this = shift;
$this->[0] or Carp::croak( 'unallowed country name' );
my $loc = Locale::SubCountry->new( $this->[0] );
my %states = $loc->full_name_code_hash;
for ( keys %states )
{
$states{ uc $_} = $states{ $_ };
delete $states{ $_ };
}
#print $states{'Tasmania'} eq 'TAS';
throw Data::Type::Exception->new( text => 'bad regionname' ) unless exists $states{ $Data::Type::value };
}
package Data::Type::Object::std_regioncode;
our @ISA = qw(Data::Type::Collection::Std::Interface::Locale);
our $VERSION = '0.01.05';
sub _depends { qw(Locale::SubCountry) }
sub desc : method { 'country region code' }
sub info : method { qq{region code} }
sub _filters : method { return ( [ 'uc' ] ) }
sub _test
{
my $this = shift;
$this->[0] or Carp::croak( 'unallowed region code' );
my %states;
eval
{
my $loc = Locale::SubCountry->new( $this->[0] );
%states = $loc->code_full_name_hash;
};
throw Data::Type::Exception->new( text => 'Local::SubCountry error: '.$@ ) if $@;
#print $states{'SA'} eq 'South Australia' ? "ok 9\n" : "not ok 9\n";
throw Data::Type::Exception->new( text => 'bad regioncode' ) unless exists $states{ $Data::Type::value };
}
package Data::Type::Object::std_countrycode;
our @ISA = qw(Data::Type::Collection::Std::Interface::Locale);
our $VERSION = '0.01.05';
sub _depends { qw(Locale::SubCountry) }
use Locale::SubCountry;
sub desc : method { 'country code' }
sub info : method { q{country code} }
sub _filters : method { return ( [ 'uc' ] ) }
sub _test
{
my $this = shift;
my %countries;
eval
{
my $world = new Locale::SubCountry::World;
%countries = $world->code_full_name_hash;
};
throw Data::Type::Exception->new( text => 'Local::SubCountry error: '.$@ ) if $@;
#print $countries{'GB'} eq 'UNITED KINGDOM' ? "ok 14\n" : "not ok 14\n";
throw Data::Type::Exception->new( text => 'bad countrycode' ) unless exists $countries{ $Data::Type::value };
}
package Data::Type::Object::std_countryname;
our @ISA = qw(Data::Type::Collection::Std::Interface::Locale);
our $VERSION = '0.01.05';
sub _depends { qw(Locale::SubCountry) }
# use Locale::SubCountry;
sub desc : method { 'country name' }
sub info : method { qq{country name} }
sub _filters : method { return ( [ 'uc' ] ) }
sub _test
{
my $this = shift;
my %countries;
eval
{
my $world = new Locale::SubCountry::World;
%countries = $world->full_name_code_hash;
};
throw Data::Type::Exception->new( text => 'Local::SubCountry error: '.$@ ) if $@;
throw Data::Type::Exception->new( text => 'this is not a country name refering to ISO' ) unless exists $countries{ $Data::Type::value };
}
package Data::Type::Object::std_zip;
our @ISA = qw(Data::Type::Collection::Std::Interface::Business);
our $VERSION = '0.01.14';
sub export { ('ZIP') }
sub _depends { qw(Regexp::Common) }
our $countries = { NL => 'Netherlands', DE => 'Germany', FR => 'France', DK => 'Denmark', BE => 'Belgian', AU => 'Australia', US => 'US' };
sub desc : method { 'zip code' }
sub info : method { q{zip code} }
sub usage : method
{
my $this = shift;
return sprintf "%s( %s )", $this->export, join( ' | ', map { qq|"$_"| } keys %$countries );
}
sub doc : method
{
return sprintf "See possible alternative for REGION from the Regexp::Common::zip perldoc. Regexp::Common 2.111 supports:\n%s.", join( ",\n", map { $countries->{$_}.qq| or "$_"| } keys %$countries );
}
sub _test : method
{
my $this = shift;
# countrycode
my $ccode = $countries->{ $this->[0] || 'US' } || $this->[0];
Data::Type::ok( 1, Data::Type::Facet::match( 'std/zip', $ccode ) );
}
package Data::Type::Object::std_date;
our @ISA = qw(Data::Type::Collection::Std::Interface::Temporal);
our $VERSION = '0.01.01';
sub _depends { qw(Date::Parse) }
sub export : method { ('DATE') }
sub desc : method { 'date' }
sub info : method { 'date (see Date::Parse)' }
sub usage : method { q{DATE employs Date::Parse str2time function.} }
sub _filters : method { return ( [ 'chomp' ] ) }
sub _test
{
my $this = shift;
#Date::Parse->language('German');
throw Data::Type::Exception(
text => 'is not a Date::Parse date',
value => $Data::Type::value,
type => __PACKAGE__
) unless Date::Parse::str2time( $Data::Type::value );
}
package Data::Type::Object::std_pod;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.36';
#
# Seems that Test::Pod is more confectioned for this work, but Pod::Find works either.
#
sub _depends { qw(Pod::Find) }
sub export : method { ('POD') }
sub desc : method { 'file containing Pod instructions' }
sub info : method { 'date (see Date::Parse)' }
sub usage : method { q{POD() requires a filename value} }
sub _filters : method { return ( [ 'chomp' ] ) }
sub _test
{
my $this = shift;
throw Data::Type::Exception(
text => 'supplied filename does not exist',
value => $Data::Type::value,
type => __PACKAGE__
) unless -e $Data::Type::value;
throw Data::Type::Exception(
text => 'supplied filename (not POD module) contains no pod information',
value => $Data::Type::value,
type => __PACKAGE__
) unless Pod::Find::contains_pod( $Data::Type::value, 0 );
}
package Data::Type::Object::std_shebang;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.36';
sub desc : method { 'file containing a she-bang (#!)' }
sub info : method { 'if the file start with #! and a signature in that line' }
sub usage : method { '( SIGNATURE [, SIGNATURE] ) - SIGNATURE is a text fragment (default: perl)' }
sub _filters : method { return ( [ 'chomp' ] ) }
sub _test
{
my $this = shift;
throw Data::Type::Exception(
text => 'supplied filename does not exist',
value => $Data::Type::value,
type => __PACKAGE__
) unless -e $Data::Type::value;
unless( open ( FILE, $Data::Type::value ) )
{
throw Data::Type::Exception(
text => $!,
value => $Data::Type::value,
type => __PACKAGE__
);
}
chomp( my $first_line = <FILE> );
my $sign_allowed = join( '|', ( @$this || qw(perl) ) );
close FILE;
throw Data::Type::Exception(
text => sprintf( 'supplied filename doesnt start with #!(%s)', $sign_allowed ),
value => $Data::Type::value,
type => __PACKAGE__
) unless $first_line =~ /#!$sign_allowed/;
}
package Data::Type::Object::std_x500;
our @ISA = qw(Data::Type::Collection::Std::Interface::Logic);
our $VERSION = '0.01.37';
sub _depends { qw(X500::DN) }
sub export : method { ('X500::DN') }
sub desc : method { 'X.500 DN (Distinguished Name)' }
sub info : method { 'distinguished names (see X500::DN)' }
sub usage : method { q{()} }
sub _filters : method { return ( [ 'chomp' ] ) }
sub _test
{
my $this = shift;
throw Data::Type::Exception(
text => sprintf "this is not a %s", $this->desc,
value => $Data::Type::value,
type => __PACKAGE__
) unless X500::DN->ParseRFC2253( $Data::Type::value );
}
package Data::Type::Object::std_xml;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.06';
sub export { ('XML') }
sub _depends { qw(XML::Parser) }
sub desc : method { 'xml markup' }
sub info : method { qq{xml markup} }
sub _test
{
my $this = shift;
eval
{
my $p = new XML::Parser();
$p->parse( $Data::Type::value ); #$p->parsefile('REC-xml-19980210.xml');
};
throw Data::Type::Exception->new( text => $@ ) if $@;
}
package Data::Type::Object::std_html;
our @ISA = qw(Data::Type::Collection::Std::Interface::String);
our $VERSION = '0.01.37';
sub export { qw(HTML) }
sub _depends { qw(HTML::Lint) }
sub desc : method { 'html markup' }
sub info : method { <<'END_HERE' }
Tests whether HTML contains invalid constructs (see HTML::Lint).
Throws Data::Type::Exception and the 'catched' member contains the array of HTML::Lint::Error (see pod) objects.
END_HERE
sub usage : method { <<END_HERE }
( 'structure' (default) | 'fluff' | 'helper' ) They are derived from the HTML::Lint->new() parameters (see HTML::Lint::Error)
END_HERE
sub _test
{
my $this = shift;
my $_alias =
{
structure => HTML::Lint::Error::STRUCTURE(),
fluff => HTML::Lint::Error::FLUFF(),
helper => HTML::Lint::Error::HELPER(),
};
my @error_sensitivity = HTML::Lint::Error::STRUCTURE();
push @error_sensitivity, ( map { $_alias->{$_} } @$this );
my $lint = HTML::Lint->new( only_types => \@error_sensitivity );
$lint->parse( $Data::Type::value ); # $lint->parse_file( $filename );
map { print "# $_\n" } split /\n/, $Data::Type::value;
throw Data::Type::Exception->new(
catched => [ $lint->errors ],
text => sprintf( 'this is not error free %s', $this->desc ),
value => $Data::Type::value,
type => __PACKAGE__,
) if scalar $lint->errors;
}
1;
=head1 NAME
Data::Type::Collection::Std - the standard set of data types
=head1 SYNOPSIS
valid '0F 0C 0A', STD::HEX;
valid '0', STD::DEFINED;
valid '234', STD::NUM( 20 );
valid '1', STD::BOOL( 'true' );
valid '100', STD::INT;
valid '1.01', STD::REAL;
valid $email, STD::EMAIL;
valid $homepage, STD::URI('http');
valid $cc, STD::CREDITCARD( 'MASTERCARD', 'VISA' );
valid $answer_a, STD::YESNO;
valid $gender, STD::GENDER;
valid 'one', STD::ENUM( qw(one two three) );
valid [qw(two six)], STD::SET( qw(one two three four five six) ) );
valid $server_ip4, STD::IP('v4');
valid $server_ip6, STD::IP('v6');
valid 'A35231AH1', STD::CINS;
valid '14565935', STD::ISSN;
valid 'DE', STD::LANGCODE;
valid 'German', STD::LANGNAME;
valid '012345678905', STD::UPC();
valid '5276440065421319', STD::CREDITCARD( 'MASTERCARD' ) );
my $foo = bless( \'123', 'SomeThing' );
valid $foo, STD::REF;
valid $foo, STD::REF( qw(SomeThing Else) );
valid [ 'bar' ], STD::REF( 'ARRAY' );
valid '80', STD::PORT;
valid 'www.cpan.org', STD::DOMAIN;
valid '<pre>hello</pre><br>', STD::HTML;
valid '<field>hello</field>', STD::XML;
=head1 TYPES
=head2 STD::BINARY (since 0.01.25)
binary code
=head3 Usage
Set of ( [0|1] )
=head2 STD::BOOL (since 0.01.25)
boolean value
=head2 STD::CINS (since 0.01.03)
CINS
=head3 Filters
L<strip|Data::Type::Filter/strip> \s
=head3 Usage
i.e. 035231AH2
=head3 Depends
L<Business::CINS>
=head2 STD::COUNTRYCODE (since 0.01.05)
country code
=head3 Depends
L<Locale::SubCountry>
=head2 STD::COUNTRYNAME (since 0.01.05)
country name
=head3 Depends
L<Locale::SubCountry>
=head2 STD::CREDITCARD (since 0.01.25)
creditcard
=head3 Filters
L<strip|Data::Type::Filter/strip> \D
=head3 Usage
CREDITCARD( Set of [MASTERCARD|AMEX|DISCOVER|BANKCARD|BLACHE|VISA|JCB|DINERS], .. )
=head3 Depends
L<Business::CreditCard>
=head2 STD::DATE (since 0.01.01)
date
=head3 Usage
DATE employs Date::Parse str2time function.
=head3 Depends
L<Date::Parse>
=head2 STD::DEFINED (since 0.01.04)
defined value
=head2 STD::DOMAIN (since 0.01.04)
domain name
=head2 STD::EMAIL (since 0.01.25)
email address
=head3 Usage
[MXCHECK as STD::BOOL]
MXCHECK results actually tests the mx host via internet (see Email::Valid)
=head3 Depends
L<Email::Valid>
=head2 STD::GENDER (since 0.01.25)
human gender
=head2 STD::GENDER::DE (since 0.01.12)
human gender
=head2 STD::HEX (since 0.01.25)
String
=head3 Filters
L<strip|Data::Type::Filter/strip> \s
=head3 Usage
Set of ( ([0-9a-fA-F]) )
=head2 STD::HTML (since 0.01.37)
html markup
=head3 Usage
( 'structure' (default) | 'fluff' | 'helper' ) They are derived from the HTML::Lint->new() parameters (see HTML::Lint::Error)
=head3 Depends
L<HTML::Lint>
=head2 STD::INT (since 0.01.27)
integer
=head3 Depends
L<Regexp::Common>
=head2 STD::IP (since 0.01.04)
IP (v4 or v6) or MAC network address
=head3 Depends
L<Regexp::Common>, L<Net::IPv6Addr>
=head2 STD::ISSN (since 0.01.03)
ISSN
=head3 Filters
L<strip|Data::Type::Filter/strip> \s
=head3 Usage
example: 14565935
=head3 Depends
L<Business::ISSN>
=head2 STD::LANGCODE (since 0.01.03)
language code
=head3 Filters
L<strip|Data::Type::Filter/strip> \s
=head3 Depends
L<Locale::Language>
=head2 STD::LANGNAME (since 0.01.03)
natural language
=head3 Filters
L<strip|Data::Type::Filter/strip> \s
=head3 Depends
L<Locale::Language>
=head2 STD::NUM (since 0.01.25)
number
=head2 STD::PATH (since 0.01.06)
path
=head2 STD::POD (since 0.01.36)
file containing Pod instructions
=head3 Usage
POD() requires a filename value
=head3 Depends
L<Pod::Find>
=head2 STD::PORT (since 0.01.04)
tcp port number
=head2 STD::QUOTED (since 0.01.25)
quoted string
=head3 Depends
L<Regexp::Common>
=head2 STD::REAL (since 0.01.25)
real
=head3 Depends
L<Regexp::Common>
=head2 STD::REF (since 0.01.25)
perl reference
=head2 STD::REGIONCODE (since 0.01.05)
country region code
=head3 Depends
L<Locale::SubCountry>
=head2 STD::REGIONNAME (since 0.01.05)
country region
=head3 Depends
L<Locale::SubCountry>
=head2 STD::SHEBANG (since 0.01.36)
file containing a she-bang (#!)
=head3 Usage
( SIGNATURE [, SIGNATURE] ) - SIGNATURE is a text fragment (default: perl)
=head2 STD::UPC (since 0.01.03)
UPC
=head3 Filters
L<strip|Data::Type::Filter/strip> \s
=head3 Usage
i.e. 012345678905
=head3 Depends
L<Business::UPC>
=head2 STD::URI (since 0.01.25)
uri
=head3 Depends
L<Regexp::Common>
=head2 STD::WORD (since 0.01.25)
word (without whitespaces)
=head2 STD::X500::DN (since 0.01.37)
X.500 DN (Distinguished Name)
=head3 Usage
()
=head3 Depends
L<X500::DN>
=head2 STD::XML (since 0.01.06)
xml markup
=head3 Depends
L<XML::Parser>
=head2 STD::YESNO (since 0.01.25)
primitiv answer
=head2 STD::YESNO::DE (since 0.01.14)
primitiv answer
=head2 STD::ZIP (since 0.01.14)
zip code
=head3 Usage
ZIP( "DE" | "AU" | "DK" | "NL" | "US" | "BE" | "FR" )
=head3 Depends
L<Regexp::Common>
=head1 INTERFACE
=head1 CONTACT
Sourceforge L<http://sf.net/projects/datatype> is hosting a project dedicated to this module. And I enjoy receiving your comments/suggestion/reports also via L<http://rt.cpan.org> or L<http://testers.cpan.org>.
=head1 AUTHOR
Murat Uenalan, <muenalan@cpan.org>