Attean
view release on metacpan or search on metacpan
lib/Attean/API/Term.pm view on Meta::CPAN
} elsif ($self->datatype->value eq 'http://www.w3.org/2001/XMLSchema#string') {
foreach my $t (@terms) {
return 0 unless ($t->does('Attean::API::Literal'));
return 0 if ($t->language);
return 0 unless (blessed($t->datatype));
return 0 unless ($t->datatype->value eq 'http://www.w3.org/2001/XMLSchema#string');
}
return 1;
}
return 0;
}
sub _ntriples_string {
my $self = shift;
my $str = sprintf('"%s"', $self->__ntriples_string);
if (my $l = $self->language) {
return join('@', $str, $l);
} else {
my $dt = $self->datatype;
if ($dt->value eq 'http://www.w3.org/2001/XMLSchema#string') {
return $str;
} else {
return join('^^', $str, $dt->ntriples_string);
}
}
}
around as_sparql => sub {
my $orig = shift;
my $self = shift;
my $s = $self->$orig(@_);
if ($s =~ m[^"(true|false)"\^\^<http://www[.]w3[.]org/2001/XMLSchema#boolean>$]) {
return $1;
}
return $s;
};
}
package Attean::API::DateTimeLiteral 0.035 {
use DateTime::Format::W3CDTF;
use Moo::Role;
sub datetime {
my $self = shift;
my $w3c = DateTime::Format::W3CDTF->new;
return $w3c->parse_datetime( $self->value );
}
}
package Attean::API::CanonicalizingLiteral 0.035 {
use Moo::Role;
requires 'canonicalized_term';
requires 'canonicalized_term_strict';
}
package Attean::API::BooleanLiteral 0.035 {
use Scalar::Util qw(blessed looks_like_number);
use Moo::Role;
sub canonicalized_term_strict {
my $self = shift;
my $value = $self->value;
if ($value =~ m/^(true|false|0|1)$/) {
return ($value eq 'true' or $value eq '1')
? Attean::Literal->true
: Attean::Literal->false;
} else {
die "Bad lexical form for xsd:boolean: '$value'";
}
}
sub canonicalized_term {
my $self = shift;
my $value = $self->value;
if ($value =~ m/^(true|false|0|1)$/) {
return ($value eq 'true' or $value eq '1')
? Attean::Literal->true
: Attean::Literal->false;
} else {
return $self;
}
}
with 'Attean::API::Literal', 'Attean::API::CanonicalizingLiteral';
}
package Attean::API::NumericLiteral 0.035 {
use Scalar::Util qw(blessed looks_like_number);
use Moo::Role;
sub equals {
my ($a, $b) = @_;
return 0 unless ($b->does('Attean::API::NumericLiteral'));
return $a->numeric_value == $b->numeric_value;
}
sub compare {
my ($a, $b) = @_;
return 1 unless blessed($b);
return 1 unless ($b->does('Attean::API::Literal') or $b->does('Attean::API::Binding'));
return -1 if ($b->does('Attean::API::Binding'));
if ($b->does('Attean::API::NumericLiteral')) {
return $a->numeric_value <=> $b->numeric_value;
} else {
return 1;
# Attean::API::Literal::compare($a, $b);
}
}
sub canonicalized_term_strict {
my $self = shift;
return $self->_canonicalized_term(1, @_);
}
sub canonicalized_term {
my $self = shift;
return $self->_canonicalized_term(0, @_);
}
sub _canonicalized_term {
my $self = shift;
my $strict = shift;
my $value = $self->value;
my $type = $self->datatype->value;
$type =~ s/^.*#//;
if ($type eq 'integer') {
if ($value =~ m/^([-+])?(\d+)$/) {
my $sign = $1 || '';
my $num = $2;
$sign = '' if ($sign eq '+');
$num =~ s/^0+(\d)/$1/;
return Attean::Literal->integer("${sign}${num}");
} else {
die "Bad lexical form for xsd:integer: '$value'" if ($strict);
return $self;
}
} elsif ($type eq 'negativeInteger') {
if ($value =~ m/^-(\d+)$/) {
my $num = $1;
$num =~ s/^0+(\d)/$1/;
return Attean::Literal->new(value => "-${num}", datatype => 'http://www.w3.org/2001/XMLSchema#negativeInteger');
} else {
die "Bad lexical form for xsd:integer: '$value'" if ($strict);
return $self;
}
} elsif ($type eq 'decimal') {
if ($value =~ m/^([-+])?((\d+)([.]\d*)?)$/) {
lib/Attean/API/Term.pm view on Meta::CPAN
} else {
die "Bad lexical form for xsd:float: '$value'" if ($strict);
return $self;
}
} elsif ($type eq 'boolean') {
if ($value =~ m/^(true|false|0|1)$/) {
return ($value eq 'true' or $value eq '1')
? Attean::Literal->true
: Attean::Literal->false;
} else {
die "Bad lexical form for xsd:boolean: '$value'" if ($strict);
return $self;
}
} elsif ($type eq 'double') {
if ($value =~ m/^(?:([-+])?(?:(\d+(?:\.\d*)?|\.\d+)([Ee][-+]?\d+)?|(INF)))|(NaN)$/) {
my $sign = $1;
my $inf = $4;
my $nan = $5;
no warnings 'uninitialized';
$sign = '' if ($sign eq '+');
return Attean::Literal->double("${sign}$inf") if ($inf);
return Attean::Literal->double($nan) if ($nan);
$value = sprintf('%E', $value);
$value =~ m/^(?:([-+])?(?:(\d+(?:\.\d*)?|\.\d+)([Ee][-+]?\d+)?|(INF)))|(NaN)$/;
$sign = $1;
$inf = $4;
$nan = $5;
my $num = $2;
my $exp = $3;
$num =~ s/[.](\d+?)0+/.$1/;
$exp =~ tr/e/E/;
$exp =~ s/E[+]/E/;
$exp =~ s/E(-?)0+([1-9])$/E$1$2/;
$exp =~ s/E(-?)0+$/E${1}0/;
return Attean::Literal->double("${sign}${num}${exp}");
} else {
die "Bad lexical form for xsd:double: '$value'" if ($strict);
return $self;
}
} else {
warn "No canonicalization for type $type";
}
return $self;
}
sub is_integer_type {
my $self = shift;
my $type = $self->datatype->value;
return scalar($type =~ qr<^http://www[.]w3[.]org/2001/XMLSchema#(?:integer|non(?:Positive|Negative)Integer|(?:positive|negative)Integer|long|int|short|byte|unsigned(?:Long|Int|Short|Byte))$>);
}
sub ebv {
my $self = shift;
return ($self->numeric_value != 0);
}
sub numeric_value {
my $self = shift;
my $v = $self->value;
return (looks_like_number($v)) ? eval $v : undef;
}
{
my %type_hierarchy = (
'integer' => 'decimal',
'nonPositiveInteger' => 'integer',
'negativeInteger' => 'nonPositiveInteger',
'long' => 'integer',
'int' => 'long',
'short' => 'int',
'byte' => 'short',
'nonNegativeInteger' => 'integer',
'unsignedLong' => 'nonNegativeInteger',
'unsignedInt' => 'unsignedLong',
'unsignedShort' => 'unsignedInt',
'unsignedByte' => 'unsignedShort',
'positiveInteger' => 'nonNegativeInteger',
);
sub _lca {
my ($lhs, $rhs) = @_;
for ($lhs, $rhs) {
s/^.*#//;
}
return "http://www.w3.org/2001/XMLSchema#$lhs" if ($lhs eq $rhs);
my $cur = $lhs;
my %ancestors = ($cur => 1);
while ($cur = $type_hierarchy{$cur}) {
$ancestors{$cur}++;
return "http://www.w3.org/2001/XMLSchema#$cur" if ($cur eq $rhs);
}
$cur = $rhs;
while ($cur = $type_hierarchy{$cur}) {
return "http://www.w3.org/2001/XMLSchema#$cur" if exists $ancestors{$cur};
}
return;
}
sub binary_promotion_type {
my $self = shift;
my $rhs = shift;
my $op = shift;
if ($op =~ m<^[-+*]$>) {
# return common numeric type
if (my $type = _lca($self->datatype->value, $rhs->datatype->value)) {
return $type;
}
return 'http://www.w3.org/2001/XMLSchema#double';
} elsif ($op eq '/') {
if ($self->is_integer_type and $rhs->is_integer_type) {
# return xsd:decimal if both operands are integers
return 'http://www.w3.org/2001/XMLSchema#decimal';
}
if (my $type = _lca($self->datatype->value, $rhs->datatype->value)) {
return $type;
}
return 'http://www.w3.org/2001/XMLSchema#double';
}
die "Unexpected numeric operation in binary_promotion_type: $op";
}
}
( run in 0.924 second using v1.01-cache-2.11-cpan-39bf76dae61 )