| line | stmt | bran | cond | sub | pod | time | code | 
| 1 | 50 |  |  | 50 |  | 561 | use v5.14; | 
|  | 50 |  |  |  |  | 150 |  | 
| 2 | 50 |  |  | 50 |  | 226 | use warnings; | 
|  | 50 |  |  |  |  | 85 |  | 
|  | 50 |  |  |  |  | 2105 |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | =head1 NAME | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | Attean::API::Term - RDF Terms | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | =head1 VERSION | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | This document describes Attean::API::Term version 0.032 | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | The Attean::API::Term role defines a common API for all RDF terms. | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =head1 REQUIRED METHODS | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | The following methods are required by the L<Attean::API::Term> role: | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =over 4 | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | =item C<< value >> | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | Returns the term's value string. | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | =item C<< ntriples_string >> | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | Returns an N-Triples-compatible string serialization. | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | =back | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | =head1 METHODS | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | This role provides default implementations of the following methods: | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | =over 4 | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | =item C<< as_string >> | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | Returns a string serialization of the term. | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | =cut | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | use Moo::Role; | 
| 45 | 50 |  |  | 50 |  | 254 |  | 
|  | 50 |  |  |  |  | 102 |  | 
|  | 50 |  |  |  |  | 321 |  | 
| 46 |  |  |  |  |  |  | with 'Attean::API::TermOrVariable', 'Attean::API::ResultOrTerm'; | 
| 47 |  |  |  |  |  |  | with 'Attean::API::TermOrVariableOrTriplePattern'; | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | requires 'value'; # => (is => 'ro', isa => 'Str', required => 1); | 
| 50 |  |  |  |  |  |  | requires 'ntriples_string'; | 
| 51 |  |  |  |  |  |  | shift->ntriples_string(); | 
| 52 |  |  |  |  |  |  | } | 
| 53 | 927 |  |  | 927 | 1 | 17198 |  | 
| 54 |  |  |  |  |  |  | =item C<< ebv >> | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | Returns true if the term has a true SPARQL "effective boolean value", false otherwise. | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | =cut | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | requires 'ebv'; | 
| 61 |  |  |  |  |  |  | requires 'compare'; | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | my $self	= shift; | 
| 64 |  |  |  |  |  |  | my $value	= $self->value; | 
| 65 |  |  |  |  |  |  | if ($value =~ m/^[\x20\x23-\x5a\x5d-\x7e]*$/o) { | 
| 66 | 491 |  |  | 491 |  | 685 | return $value; | 
| 67 | 491 |  |  |  |  | 1027 | } | 
| 68 | 491 | 100 |  |  |  | 1559 |  | 
| 69 | 490 |  |  |  |  | 6762 | my @chars	= split(//, $value); | 
| 70 |  |  |  |  |  |  | my $string	= ''; | 
| 71 |  |  |  |  |  |  | while (scalar(@chars)) { | 
| 72 | 1 |  |  |  |  | 7 | my $c	= shift(@chars); | 
| 73 | 1 |  |  |  |  | 2 | my $o	= ord($c); | 
| 74 | 1 |  |  |  |  | 3 | if ($o < 0x8) { | 
| 75 | 20 |  |  |  |  | 19 | $string	.= sprintf("\\u%04X", $o); | 
| 76 | 20 |  |  |  |  | 20 | } elsif ($o == 0x9) { | 
| 77 | 20 | 50 |  |  |  | 63 | $string	.= "\\t"; | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 78 | 0 |  |  |  |  | 0 | } elsif ($o == 0xA) { | 
| 79 |  |  |  |  |  |  | $string	.= "\\n"; | 
| 80 | 0 |  |  |  |  | 0 | } elsif ($o < 0xC) { | 
| 81 |  |  |  |  |  |  | $string	.= sprintf("\\u%04X", $o); | 
| 82 | 0 |  |  |  |  | 0 | } elsif ($o == 0xD) { | 
| 83 |  |  |  |  |  |  | $string	.= "\\r"; | 
| 84 | 0 |  |  |  |  | 0 | } elsif ($o < 0x1F) { | 
| 85 |  |  |  |  |  |  | $string	.= sprintf("\\u%04X", $o); | 
| 86 | 0 |  |  |  |  | 0 | } elsif ($o < 0x21) { | 
| 87 |  |  |  |  |  |  | $string	.= $c; | 
| 88 | 0 |  |  |  |  | 0 | } elsif ($o == 0x22) { | 
| 89 |  |  |  |  |  |  | $string	.= "\""; | 
| 90 | 0 |  |  |  |  | 0 | } elsif ($o < 0x5B) { | 
| 91 |  |  |  |  |  |  | $string	.= $c; | 
| 92 | 0 |  |  |  |  | 0 | } elsif ($o == 0x5C) { | 
| 93 |  |  |  |  |  |  | $string	.= "\\"; | 
| 94 | 5 |  |  |  |  | 7 | } elsif ($o < 0x7E) { | 
| 95 |  |  |  |  |  |  | $string	.= $c; | 
| 96 | 0 |  |  |  |  | 0 | } elsif ($o < 0xFFFF) { | 
| 97 |  |  |  |  |  |  | $string	.= sprintf("\\u%04X", $o); | 
| 98 | 14 |  |  |  |  | 18 | } else { | 
| 99 |  |  |  |  |  |  | $string	.= sprintf("\\U%08X", $o); | 
| 100 | 1 |  |  |  |  | 5 | } | 
| 101 |  |  |  |  |  |  | } | 
| 102 | 0 |  |  |  |  | 0 | return $string; | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 1 |  |  |  |  | 17 | with 'Attean::API::TermOrTriple'; | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | use IRI; | 
| 109 |  |  |  |  |  |  | use Scalar::Util qw(blessed); | 
| 110 |  |  |  |  |  |  | use Types::Standard qw(Maybe Str ConsumerOf); | 
| 111 |  |  |  |  |  |  | use AtteanX::SPARQL::Constants; | 
| 112 | 50 |  |  | 50 |  | 56424 | use AtteanX::SPARQL::Token; | 
|  | 50 |  |  |  |  | 2456330 |  | 
|  | 50 |  |  |  |  | 8553 |  | 
| 113 | 50 |  |  | 50 |  | 511 | use Attean::API::Query; | 
|  | 50 |  |  |  |  | 98 |  | 
|  | 50 |  |  |  |  | 2881 |  | 
| 114 | 50 |  |  | 50 |  | 285 |  | 
|  | 50 |  |  |  |  | 100 |  | 
|  | 50 |  |  |  |  | 450 |  | 
| 115 | 50 |  |  | 50 |  | 36314 | use Moo::Role; | 
|  | 50 |  |  |  |  | 97 |  | 
|  | 50 |  |  |  |  | 7039 |  | 
| 116 | 50 |  |  | 50 |  | 292 |  | 
|  | 50 |  |  |  |  | 93 |  | 
|  | 50 |  |  |  |  | 883 |  | 
| 117 | 50 |  |  | 50 |  | 22422 | with 'Attean::API::Term'; | 
|  | 50 |  |  |  |  | 205 |  | 
|  | 50 |  |  |  |  | 2085 |  | 
| 118 |  |  |  |  |  |  | with 'Attean::API::SPARQLSerializable'; | 
| 119 | 50 |  |  | 50 |  | 395 | with 'Attean::API::TermOrVariableOrTriplePattern'; | 
|  | 50 |  |  |  |  | 88 |  | 
|  | 50 |  |  |  |  | 185 |  | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | requires 'language'; # => (is => 'ro', isa => 'Maybe[Str]', predicate => 'has_language'); | 
| 122 |  |  |  |  |  |  | requires 'datatype'; # => (is => 'ro', isa => 'Attean::API::IRI', required => 1, coerce => 1, default => sub { IRI->new(value => 'http://www.w3.org/2001/XMLSchema#string') }); | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | around 'BUILDARGS' => sub { | 
| 125 |  |  |  |  |  |  | my $orig	= shift; | 
| 126 |  |  |  |  |  |  | my $class	= shift; | 
| 127 |  |  |  |  |  |  | my $args	= $class->$orig(@_); | 
| 128 |  |  |  | 443 | 0 |  | if (my $lang = $args->{language}) { | 
| 129 |  |  |  |  |  |  | my $oldlang	= $lang; | 
| 130 |  |  |  |  |  |  | # http://tools.ietf.org/html/bcp47#section-2.1.1 | 
| 131 |  |  |  |  |  |  | # All subtags use lowercase letters | 
| 132 |  |  |  |  |  |  | $lang	= lc($lang); | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | # with 2 exceptions: subtags that neither appear at the start of the tag nor occur after singletons | 
| 135 |  |  |  |  |  |  | # i.e. there's a subtag of length at least 2 preceding the exception; and a following subtag or end-of-tag | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | # 1. two-letter subtags are all uppercase | 
| 138 |  |  |  |  |  |  | $lang	=~ s{(?<=\w\w-)(\w\w)(?=($|-))}{\U$1}g; | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | # 2. four-letter subtags are titlecase | 
| 141 |  |  |  |  |  |  | $lang	=~ s{(?<=\w\w-)(\w\w\w\w)(?=($|-))}{\u\L$1}g; | 
| 142 |  |  |  |  |  |  | $args->{language}	= $lang; | 
| 143 |  |  |  |  |  |  | } | 
| 144 |  |  |  |  |  |  | return $args; | 
| 145 |  |  |  |  |  |  | }; | 
| 146 |  |  |  |  |  |  | around 'BUILD' => sub { | 
| 147 |  |  |  |  |  |  | my $orig	= shift; | 
| 148 |  |  |  |  |  |  | my $self	= shift; | 
| 149 |  |  |  |  |  |  | $self->$orig(@_); | 
| 150 |  |  |  |  |  |  | if (my $dt = $self->datatype) { | 
| 151 |  |  |  |  |  |  | my $type	= $dt->value; | 
| 152 |  |  |  |  |  |  | if ($type =~ qr<^http://www[.]w3[.]org/2001/XMLSchema#(?:integer|decimal|float|double|non(?:Positive|Negative)Integer|(?:positive|negative)Integer|long|int|short|byte|unsigned(?:Long|Int|Short|Byte))$>) { | 
| 153 |  |  |  |  |  |  | Moo::Role->apply_roles_to_object($self, 'Attean::API::NumericLiteral'); | 
| 154 |  |  |  |  |  |  | } elsif ($type eq 'http://www.w3.org/2001/XMLSchema#boolean') { | 
| 155 |  |  |  |  |  |  | Moo::Role->apply_roles_to_object($self, 'Attean::API::BooleanLiteral'); | 
| 156 |  |  |  |  |  |  | } elsif ($type eq 'http://www.w3.org/2001/XMLSchema#dateTime') { | 
| 157 |  |  |  |  |  |  | Moo::Role->apply_roles_to_object($self, 'Attean::API::DateTimeLiteral'); | 
| 158 |  |  |  |  |  |  | } | 
| 159 |  |  |  |  |  |  | } | 
| 160 |  |  |  |  |  |  | }; | 
| 161 |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | my $self	= shift; | 
| 163 |  |  |  |  |  |  | my @tokens; | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | my $dt = $self->datatype; | 
| 166 |  |  |  |  |  |  | if ($self->does('Attean::API::NumericLiteral') and $dt->value eq 'http://www.w3.org/2001/XMLSchema#integer') { | 
| 167 |  |  |  |  |  |  | if ($self->value =~ /^\d+$/) { | 
| 168 | 86 |  |  | 86 | 0 | 2666 | my $t	= AtteanX::SPARQL::Token->fast_constructor( INTEGER, -1, -1, -1, -1, [$self->value] ); | 
| 169 | 86 |  |  |  |  | 100 | return Attean::ListIterator->new( values => [$t], item_type => 'AtteanX::SPARQL::Token' ); | 
| 170 |  |  |  |  |  |  | } | 
| 171 | 86 |  |  |  |  | 1511 | } | 
| 172 | 86 | 100 | 66 |  |  | 1511 |  | 
| 173 | 16 | 50 |  |  |  | 360 | my $t	= AtteanX::SPARQL::Token->fast_constructor( STRING1D, -1, -1, -1, -1, [$self->value] ); | 
| 174 | 16 |  |  |  |  | 76 | push(@tokens, $t); | 
| 175 | 16 |  |  |  |  | 925 | if (my $lang = $self->language) { | 
| 176 |  |  |  |  |  |  | my $l	= AtteanX::SPARQL::Token->fast_constructor( LANG, -1, -1, -1, -1, ["$lang"] ); | 
| 177 |  |  |  |  |  |  | push(@tokens, $l); | 
| 178 |  |  |  |  |  |  | } else { | 
| 179 | 70 |  |  |  |  | 1609 | if ($dt->value ne 'http://www.w3.org/2001/XMLSchema#string') { | 
| 180 | 70 |  |  |  |  | 3046 | push(@tokens, AtteanX::SPARQL::Token->hathat); | 
| 181 | 70 | 100 |  |  |  | 269 | push(@tokens, $dt->sparql_tokens->elements); | 
| 182 | 6 |  |  |  |  | 27 | } | 
| 183 | 6 |  |  |  |  | 229 | } | 
| 184 |  |  |  |  |  |  | return Attean::ListIterator->new( values => \@tokens, item_type => 'AtteanX::SPARQL::Token' ); | 
| 185 | 64 | 100 |  |  |  | 240 | } | 
| 186 | 2 |  |  |  |  | 8 |  | 
| 187 | 2 |  |  |  |  | 80 | my $self	= shift; | 
| 188 |  |  |  |  |  |  | my $value	= $self->value; | 
| 189 |  |  |  |  |  |  | my $dt		= $self->datatype->value; | 
| 190 | 70 |  |  |  |  | 1164 | if ($dt eq 'http://www.w3.org/2001/XMLSchema#boolean') { | 
| 191 |  |  |  |  |  |  | return ($value eq 'true' or $value eq '1'); | 
| 192 |  |  |  |  |  |  | } else { | 
| 193 |  |  |  |  |  |  | return (length($value) > 0); | 
| 194 | 28 |  |  | 28 | 1 | 51 | } | 
| 195 | 28 |  |  |  |  | 87 | } | 
| 196 | 28 |  |  |  |  | 540 |  | 
| 197 | 28 | 100 |  |  |  | 76 | my ($a, $b)	= @_; | 
| 198 | 26 |  | 66 |  |  | 234 | return 1 unless blessed($b); | 
| 199 |  |  |  |  |  |  | return 1 unless ($b->does('Attean::API::Literal') or $b->does('Attean::API::Binding')); | 
| 200 | 2 |  |  |  |  | 8 | return -1 if ($b->does('Attean::API::Binding')); | 
| 201 |  |  |  |  |  |  | my $c	= ((($a->language // '') cmp ($b->language // '')) || ($a->datatype->value cmp $b->datatype->value) || ($a->value cmp $b->value)); | 
| 202 |  |  |  |  |  |  | return $c; | 
| 203 |  |  |  |  |  |  | } | 
| 204 |  |  |  |  |  |  |  | 
| 205 | 1 |  |  | 1 | 1 | 5 | if ($ENV{ATTEAN_TYPECHECK}) { | 
| 206 | 1 | 50 |  |  |  | 5 | my %map	= ( | 
| 207 | 1 | 50 | 33 |  |  | 4 | language	=> Maybe[Str], | 
| 208 | 1 | 50 |  |  |  | 19 | datatype	=> ConsumerOf['Attean::API::IRI'], | 
| 209 | 1 |  | 33 |  |  | 39 | ); | 
| 210 | 1 |  |  |  |  | 3 | foreach my $method (keys %map) { | 
| 211 |  |  |  |  |  |  | my $type	= $map{$method}; | 
| 212 |  |  |  |  |  |  | around $method => sub { | 
| 213 |  |  |  |  |  |  | my $orig	= shift; | 
| 214 |  |  |  |  |  |  | my $self	= shift; | 
| 215 |  |  |  |  |  |  | my $class	= ref($self); | 
| 216 |  |  |  |  |  |  | my $value	= $self->$orig(@_); | 
| 217 |  |  |  |  |  |  | my $err		= $type->validate($value); | 
| 218 |  |  |  |  |  |  | if ($err) { | 
| 219 |  |  |  |  |  |  | my $name	= $type->display_name; | 
| 220 |  |  |  |  |  |  | die "${class}'s $method failed conformance check for $name: $value"; | 
| 221 |  |  |  |  |  |  | } | 
| 222 |  |  |  |  |  |  | return $value; | 
| 223 |  |  |  |  |  |  | }; | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | my $self	= shift; | 
| 228 |  |  |  |  |  |  | my %args; | 
| 229 |  |  |  |  |  |  | $args{language}	= $self->language if ($self->language); | 
| 230 |  |  |  |  |  |  | $args{datatype}	= $self->datatype if ($self->datatype); | 
| 231 |  |  |  |  |  |  | return %args; | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | my $self	= shift; | 
| 235 |  |  |  |  |  |  | my @terms	= @_; | 
| 236 | 0 |  |  | 0 | 0 | 0 |  | 
| 237 | 0 |  |  |  |  | 0 | if (my $l = $self->language) { | 
| 238 | 0 | 0 |  |  |  | 0 | foreach my $t (@terms) { | 
| 239 | 0 | 0 |  |  |  | 0 | return 0 unless ($t->does('Attean::API::Literal')); | 
| 240 | 0 |  |  |  |  | 0 | if ($t->language) { | 
| 241 |  |  |  |  |  |  | return 0 unless (defined($t->language)); | 
| 242 |  |  |  |  |  |  | return 0 unless ($t->language eq $l); | 
| 243 |  |  |  |  |  |  | } else { | 
| 244 | 0 |  |  | 0 | 0 | 0 | return 0 unless ($t->datatype->value eq 'http://www.w3.org/2001/XMLSchema#string'); | 
| 245 | 0 |  |  |  |  | 0 | } | 
| 246 |  |  |  |  |  |  | } | 
| 247 | 0 | 0 |  |  |  | 0 | return 1; | 
|  |  | 0 |  |  |  |  |  | 
| 248 | 0 |  |  |  |  | 0 | } elsif ($self->datatype->value eq 'http://www.w3.org/2001/XMLSchema#string') { | 
| 249 | 0 | 0 |  |  |  | 0 | foreach my $t (@terms) { | 
| 250 | 0 | 0 |  |  |  | 0 | return 0 unless ($t->does('Attean::API::Literal')); | 
| 251 | 0 | 0 |  |  |  | 0 | return 0 if ($t->language); | 
| 252 | 0 | 0 |  |  |  | 0 | return 0 unless (blessed($t->datatype)); | 
| 253 |  |  |  |  |  |  | return 0 unless ($t->datatype->value eq 'http://www.w3.org/2001/XMLSchema#string'); | 
| 254 | 0 | 0 |  |  |  | 0 | } | 
| 255 |  |  |  |  |  |  | return 1; | 
| 256 |  |  |  |  |  |  | } | 
| 257 | 0 |  |  |  |  | 0 |  | 
| 258 |  |  |  |  |  |  | return 0; | 
| 259 | 0 |  |  |  |  | 0 | } | 
| 260 | 0 | 0 |  |  |  | 0 |  | 
| 261 | 0 | 0 |  |  |  | 0 | my $self	= shift; | 
| 262 | 0 | 0 |  |  |  | 0 | my $str		= sprintf('"%s"', $self->__ntriples_string); | 
| 263 | 0 | 0 |  |  |  | 0 | if (my $l = $self->language) { | 
| 264 |  |  |  |  |  |  | return join('@', $str, $l); | 
| 265 | 0 |  |  |  |  | 0 | } else { | 
| 266 |  |  |  |  |  |  | my $dt	= $self->datatype; | 
| 267 |  |  |  |  |  |  | if ($dt->value eq 'http://www.w3.org/2001/XMLSchema#string') { | 
| 268 | 0 |  |  |  |  | 0 | return $str; | 
| 269 |  |  |  |  |  |  | } else { | 
| 270 |  |  |  |  |  |  | return join('^^', $str, $dt->ntriples_string); | 
| 271 |  |  |  |  |  |  | } | 
| 272 | 64 |  |  | 64 |  | 1524 | } | 
| 273 | 64 |  |  |  |  | 235 | } | 
| 274 | 64 | 50 |  |  |  | 283 |  | 
| 275 | 0 |  |  |  |  | 0 | around as_sparql => sub { | 
| 276 |  |  |  |  |  |  | my $orig	= shift; | 
| 277 | 64 |  |  |  |  | 1152 | my $self	= shift; | 
| 278 | 64 | 50 |  |  |  | 258 | my $s		= $self->$orig(@_); | 
| 279 | 0 |  |  |  |  | 0 |  | 
| 280 |  |  |  |  |  |  | if ($s =~ m[^"(true|false)"\^\^<http://www[.]w3[.]org/2001/XMLSchema#boolean>$]) { | 
| 281 | 64 |  |  |  |  | 945 | return $1; | 
| 282 |  |  |  |  |  |  | } | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | return $s; | 
| 285 |  |  |  |  |  |  | }; | 
| 286 |  |  |  |  |  |  | } | 
| 287 |  |  |  |  |  |  |  | 
| 288 |  |  |  |  |  |  | use DateTime::Format::W3CDTF; | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | use Moo::Role; | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | my $self	= shift; | 
| 293 |  |  |  |  |  |  | my $w3c	= DateTime::Format::W3CDTF->new; | 
| 294 |  |  |  |  |  |  | return $w3c->parse_datetime( $self->value ); | 
| 295 |  |  |  |  |  |  | } | 
| 296 |  |  |  |  |  |  | } | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | use Moo::Role; | 
| 299 |  |  |  |  |  |  | requires 'canonicalized_term'; | 
| 300 | 50 |  |  | 50 |  | 108766 | } | 
|  | 50 |  |  |  |  | 20849485 |  | 
|  | 50 |  |  |  |  | 1851 |  | 
| 301 |  |  |  |  |  |  |  | 
| 302 | 50 |  |  | 50 |  | 514 | use Scalar::Util qw(blessed looks_like_number); | 
|  | 50 |  |  |  |  | 106 |  | 
|  | 50 |  |  |  |  | 480 |  | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | use Moo::Role; | 
| 305 | 0 |  |  | 0 | 0 | 0 |  | 
| 306 | 0 |  |  |  |  | 0 | my $self	= shift; | 
| 307 | 0 |  |  |  |  | 0 | my $value	= $self->value; | 
| 308 |  |  |  |  |  |  | if ($value =~ m/^(true|false|0|1)$/) { | 
| 309 |  |  |  |  |  |  | return ($value eq 'true' or $value eq '1') | 
| 310 |  |  |  |  |  |  | ? Attean::Literal->true | 
| 311 |  |  |  |  |  |  | : Attean::Literal->false; | 
| 312 | 50 |  |  | 50 |  | 23539 | } else { | 
|  | 50 |  |  |  |  | 109 |  | 
|  | 50 |  |  |  |  | 209 |  | 
| 313 |  |  |  |  |  |  | die "Bad lexical form for xsd:boolean: '$value'"; | 
| 314 |  |  |  |  |  |  | } | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  | with 'Attean::API::Literal', 'Attean::API::CanonicalizingLiteral'; | 
| 317 | 50 |  |  | 50 |  | 16673 | } | 
|  | 50 |  |  |  |  | 117 |  | 
|  | 50 |  |  |  |  | 3051 |  | 
| 318 |  |  |  |  |  |  |  | 
| 319 | 50 |  |  | 50 |  | 308 | use Scalar::Util qw(blessed looks_like_number); | 
|  | 50 |  |  |  |  | 124 |  | 
|  | 50 |  |  |  |  | 217 |  | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | use Moo::Role; | 
| 322 | 0 |  |  | 0 | 0 | 0 |  | 
| 323 | 0 |  |  |  |  | 0 | my ($a, $b)	= @_; | 
| 324 | 0 | 0 |  |  |  | 0 | return 1 unless blessed($b); | 
| 325 | 0 | 0 | 0 |  |  | 0 | return 1 unless ($b->does('Attean::API::Literal') or $b->does('Attean::API::Binding')); | 
| 326 |  |  |  |  |  |  | return -1 if ($b->does('Attean::API::Binding')); | 
| 327 |  |  |  |  |  |  | if ($b->does('Attean::API::NumericLiteral')) { | 
| 328 |  |  |  |  |  |  | return $a->numeric_value <=> $b->numeric_value; | 
| 329 | 0 |  |  |  |  | 0 | } else { | 
| 330 |  |  |  |  |  |  | return 1; | 
| 331 |  |  |  |  |  |  | # 			Attean::API::Literal::compare($a, $b); | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  | } | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | my $self	= shift; | 
| 336 | 50 |  |  | 50 |  | 24692 | my $value	= $self->value; | 
|  | 50 |  |  |  |  | 111 |  | 
|  | 50 |  |  |  |  | 2288 |  | 
| 337 |  |  |  |  |  |  | my $type	= $self->datatype->value; | 
| 338 | 50 |  |  | 50 |  | 310 | $type		=~ s/^.*#//; | 
|  | 50 |  |  |  |  | 113 |  | 
|  | 50 |  |  |  |  | 274 |  | 
| 339 |  |  |  |  |  |  | if ($type eq 'integer') { | 
| 340 |  |  |  |  |  |  | if ($value =~ m/^([-+])?(\d+)$/) { | 
| 341 | 1 |  |  | 1 | 0 | 732 | my $sign	= $1 || ''; | 
| 342 | 1 | 50 |  |  |  | 6 | my $num		= $2; | 
| 343 | 1 | 50 | 33 |  |  | 4 | $sign		= '' if ($sign eq '+'); | 
| 344 | 1 | 50 |  |  |  | 16 | $num		=~ s/^0+(\d)/$1/; | 
| 345 | 1 | 50 |  |  |  | 19 | return Attean::Literal->integer("${sign}${num}"); | 
| 346 | 1 |  |  |  |  | 11 | } else { | 
| 347 |  |  |  |  |  |  | die "Bad lexical form for xsd:integer: '$value'"; | 
| 348 | 0 |  |  |  |  | 0 | } | 
| 349 |  |  |  |  |  |  | } elsif ($type eq 'negativeInteger') { | 
| 350 |  |  |  |  |  |  | if ($value =~ m/^-(\d+)$/) { | 
| 351 |  |  |  |  |  |  | my $num		= $1; | 
| 352 |  |  |  |  |  |  | $num		=~ s/^0+(\d)/$1/; | 
| 353 |  |  |  |  |  |  | return Attean::Literal->new(value => "-${num}", datatype => 'http://www.w3.org/2001/XMLSchema#negativeInteger'); | 
| 354 | 5 |  |  | 5 | 0 | 78 | } else { | 
| 355 | 5 |  |  |  |  | 16 | die "Bad lexical form for xsd:integer: '$value'"; | 
| 356 | 5 |  |  |  |  | 95 | } | 
| 357 | 5 |  |  |  |  | 19 | } elsif ($type eq 'decimal') { | 
| 358 | 5 | 100 |  |  |  | 18 | if ($value =~ m/^([-+])?((\d+)([.]\d*)?)$/) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 359 | 1 | 50 |  |  |  | 3 | my $sign	= $1 || ''; | 
| 360 | 1 |  | 50 |  |  | 5 | my $num		= $2; | 
| 361 | 1 |  |  |  |  | 2 | my $int		= $3; | 
| 362 | 1 | 50 |  |  |  | 4 | my $frac	= $4; | 
| 363 | 1 |  |  |  |  | 2 | $sign		= '' if ($sign eq '+'); | 
| 364 | 1 |  |  |  |  | 3 | $num		=~ s/^0+(.)/$1/; | 
| 365 |  |  |  |  |  |  | $num		=~ s/[.](\d+)0+$/.$1/; | 
| 366 | 0 |  |  |  |  | 0 | if ($num =~ /^[.]/) { | 
| 367 |  |  |  |  |  |  | $num	= "0$num"; | 
| 368 |  |  |  |  |  |  | } | 
| 369 | 0 | 0 |  |  |  | 0 | if ($num !~ /[.]/) { | 
| 370 | 0 |  |  |  |  | 0 | $num	= "${num}.0"; | 
| 371 | 0 |  |  |  |  | 0 | } | 
| 372 | 0 |  |  |  |  | 0 | return Attean::Literal->decimal("${sign}${num}"); | 
| 373 |  |  |  |  |  |  | } elsif ($value =~ m/^([-+])?([.]\d+)$/) { | 
| 374 | 0 |  |  |  |  | 0 | my $sign	= $1 || ''; | 
| 375 |  |  |  |  |  |  | my $num		= $2; | 
| 376 |  |  |  |  |  |  | $sign		= '' if ($sign eq '+'); | 
| 377 | 4 | 50 |  |  |  | 28 | $num		=~ s/^0+(.)/$1/; | 
|  |  | 0 |  |  |  |  |  | 
| 378 | 4 |  | 50 |  |  | 18 | return Attean::Literal->decimal("${sign}${num}"); | 
| 379 | 4 |  |  |  |  | 7 | } else { | 
| 380 | 4 |  |  |  |  | 8 | die "Bad lexical form for xsd:deciaml: '$value'"; | 
| 381 | 4 |  |  |  |  | 7 | } | 
| 382 | 4 | 50 |  |  |  | 7 | } elsif ($type eq 'float') { | 
| 383 | 4 |  |  |  |  | 9 | if ($value =~ m/^(?:([-+])?(?:(\d+(?:\.\d*)?|\.\d+)([Ee][-+]?\d+)?|(INF)))|(NaN)$/) { | 
| 384 | 4 |  |  |  |  | 7 | my $sign	= $1; | 
| 385 | 4 | 50 |  |  |  | 9 | my $inf		= $4; | 
| 386 | 0 |  |  |  |  | 0 | my $nan		= $5; | 
| 387 |  |  |  |  |  |  | no warnings 'uninitialized'; | 
| 388 | 4 | 50 |  |  |  | 10 | $sign		= '' if ($sign eq '+'); | 
| 389 | 4 |  |  |  |  | 6 | return Attean::Literal->float("${sign}$inf") if ($inf); | 
| 390 |  |  |  |  |  |  | return Attean::Literal->float($nan) if ($nan); | 
| 391 | 4 |  |  |  |  | 18 |  | 
| 392 |  |  |  |  |  |  | $value		= sprintf('%E', $value); | 
| 393 | 0 |  | 0 |  |  | 0 | $value 		=~ m/^(?:([-+])?(?:(\d+(?:\.\d*)?|\.\d+)([Ee][-+]?\d+)?|(INF)))|(NaN)$/; | 
| 394 | 0 |  |  |  |  | 0 | $sign		= $1; | 
| 395 | 0 | 0 |  |  |  | 0 | $inf		= $4; | 
| 396 | 0 |  |  |  |  | 0 | $nan		= $5; | 
| 397 | 0 |  |  |  |  | 0 | my $num		= $2; | 
| 398 |  |  |  |  |  |  | my $exp		= $3; | 
| 399 | 0 |  |  |  |  | 0 | $num		=~ s/[.](\d+?)0+/.$1/; | 
| 400 |  |  |  |  |  |  | $exp	=~ tr/e/E/; | 
| 401 |  |  |  |  |  |  | $exp	=~ s/E[+]/E/; | 
| 402 | 0 | 0 |  |  |  | 0 | $exp	=~ s/E(-?)0+([1-9])$/E$1$2/; | 
| 403 | 0 |  |  |  |  | 0 | $exp	=~ s/E(-?)0+$/E${1}0/; | 
| 404 | 0 |  |  |  |  | 0 | return Attean::Literal->float("${sign}${num}${exp}"); | 
| 405 | 0 |  |  |  |  | 0 | } else { | 
| 406 | 50 |  |  | 50 |  | 50034 | die "Bad lexical form for xsd:float: '$value'"; | 
|  | 50 |  |  |  |  | 113 |  | 
|  | 50 |  |  |  |  | 20986 |  | 
| 407 | 0 | 0 |  |  |  | 0 | } | 
| 408 | 0 | 0 |  |  |  | 0 | } elsif ($type eq 'boolean') { | 
| 409 | 0 | 0 |  |  |  | 0 | if ($value =~ m/^(true|false|0|1)$/) { | 
| 410 |  |  |  |  |  |  | return ($value eq 'true' or $value eq '1') | 
| 411 | 0 |  |  |  |  | 0 | ? Attean::Literal->true | 
| 412 | 0 |  |  |  |  | 0 | : Attean::Literal->false; | 
| 413 | 0 |  |  |  |  | 0 | } else { | 
| 414 | 0 |  |  |  |  | 0 | die "Bad lexical form for xsd:boolean: '$value'"; | 
| 415 | 0 |  |  |  |  | 0 | } | 
| 416 | 0 |  |  |  |  | 0 | } elsif ($type eq 'double') { | 
| 417 | 0 |  |  |  |  | 0 | if ($value =~ m/^(?:([-+])?(?:(\d+(?:\.\d*)?|\.\d+)([Ee][-+]?\d+)?|(INF)))|(NaN)$/) { | 
| 418 | 0 |  |  |  |  | 0 | my $sign	= $1; | 
| 419 | 0 |  |  |  |  | 0 | my $inf		= $4; | 
| 420 | 0 |  |  |  |  | 0 | my $nan		= $5; | 
| 421 | 0 |  |  |  |  | 0 | no warnings 'uninitialized'; | 
| 422 | 0 |  |  |  |  | 0 | $sign		= '' if ($sign eq '+'); | 
| 423 | 0 |  |  |  |  | 0 | return Attean::Literal->double("${sign}$inf") if ($inf); | 
| 424 |  |  |  |  |  |  | return Attean::Literal->double($nan) if ($nan); | 
| 425 | 0 |  |  |  |  | 0 |  | 
| 426 |  |  |  |  |  |  | $value		= sprintf('%E', $value); | 
| 427 |  |  |  |  |  |  | $value 		=~ m/^(?:([-+])?(?:(\d+(?:\.\d*)?|\.\d+)([Ee][-+]?\d+)?|(INF)))|(NaN)$/; | 
| 428 | 0 | 0 |  |  |  | 0 | $sign		= $1; | 
| 429 | 0 | 0 | 0 |  |  | 0 | $inf		= $4; | 
| 430 |  |  |  |  |  |  | $nan		= $5; | 
| 431 |  |  |  |  |  |  | my $num		= $2; | 
| 432 |  |  |  |  |  |  | my $exp		= $3; | 
| 433 | 0 |  |  |  |  | 0 | $num		=~ s/[.](\d+?)0+/.$1/; | 
| 434 |  |  |  |  |  |  | $exp	=~ tr/e/E/; | 
| 435 |  |  |  |  |  |  | $exp	=~ s/E[+]/E/; | 
| 436 | 0 | 0 |  |  |  | 0 | $exp	=~ s/E(-?)0+([1-9])$/E$1$2/; | 
| 437 | 0 |  |  |  |  | 0 | $exp	=~ s/E(-?)0+$/E${1}0/; | 
| 438 | 0 |  |  |  |  | 0 | return Attean::Literal->double("${sign}${num}${exp}"); | 
| 439 | 0 |  |  |  |  | 0 | } else { | 
| 440 | 50 |  |  | 50 |  | 375 | die "Bad lexical form for xsd:double: '$value'"; | 
|  | 50 |  |  |  |  | 108 |  | 
|  | 50 |  |  |  |  | 42991 |  | 
| 441 | 0 | 0 |  |  |  | 0 | } | 
| 442 | 0 | 0 |  |  |  | 0 | } else { | 
| 443 | 0 | 0 |  |  |  | 0 | warn "No canonicalization for type $type"; | 
| 444 |  |  |  |  |  |  | } | 
| 445 | 0 |  |  |  |  | 0 | return $self; | 
| 446 | 0 |  |  |  |  | 0 | } | 
| 447 | 0 |  |  |  |  | 0 |  | 
| 448 | 0 |  |  |  |  | 0 | my $self	= shift; | 
| 449 | 0 |  |  |  |  | 0 | my $type	= $self->datatype->value; | 
| 450 | 0 |  |  |  |  | 0 | 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))$>); | 
| 451 | 0 |  |  |  |  | 0 | } | 
| 452 | 0 |  |  |  |  | 0 |  | 
| 453 | 0 |  |  |  |  | 0 | my $self	= shift; | 
| 454 | 0 |  |  |  |  | 0 | return ($self->numeric_value != 0); | 
| 455 | 0 |  |  |  |  | 0 | } | 
| 456 | 0 |  |  |  |  | 0 |  | 
| 457 | 0 |  |  |  |  | 0 | my $self	= shift; | 
| 458 |  |  |  |  |  |  | my $v		= $self->value; | 
| 459 | 0 |  |  |  |  | 0 | return (looks_like_number($v)) ? eval $v : undef; | 
| 460 |  |  |  |  |  |  | } | 
| 461 |  |  |  |  |  |  |  | 
| 462 | 0 |  |  |  |  | 0 | { | 
| 463 |  |  |  |  |  |  | my %type_hierarchy	= ( | 
| 464 | 0 |  |  |  |  | 0 | 'integer'				=> 'decimal', | 
| 465 |  |  |  |  |  |  | 'nonPositiveInteger'	=> 'integer', | 
| 466 |  |  |  |  |  |  | 'negativeInteger'		=> 'nonPositiveInteger', | 
| 467 |  |  |  |  |  |  | 'long'					=> 'integer', | 
| 468 | 28 |  |  | 28 | 0 | 40 | 'int'					=> 'long', | 
| 469 | 28 |  |  |  |  | 440 | 'short'					=> 'int', | 
| 470 | 28 |  |  |  |  | 220 | 'byte'					=> 'short', | 
| 471 |  |  |  |  |  |  | 'nonNegativeInteger'	=> 'integer', | 
| 472 |  |  |  |  |  |  | 'unsignedLong'			=> 'nonNegativeInteger', | 
| 473 |  |  |  |  |  |  | 'unsignedInt'			=> 'unsignedLong', | 
| 474 | 6 |  |  | 6 | 0 | 2052 | 'unsignedShort'			=> 'unsignedInt', | 
| 475 | 6 |  |  |  |  | 17 | 'unsignedByte'			=> 'unsignedShort', | 
| 476 |  |  |  |  |  |  | 'positiveInteger'		=> 'nonNegativeInteger', | 
| 477 |  |  |  |  |  |  | ); | 
| 478 |  |  |  |  |  |  | my ($lhs, $rhs)	= @_; | 
| 479 | 46 |  |  | 46 | 0 | 2233 | for ($lhs, $rhs) { | 
| 480 | 46 |  |  |  |  | 100 | s/^.*#//; | 
| 481 | 46 | 50 |  |  |  | 1684 | } | 
| 482 |  |  |  |  |  |  | return "http://www.w3.org/2001/XMLSchema#$lhs" if ($lhs eq $rhs); | 
| 483 |  |  |  |  |  |  | my $cur	= $lhs; | 
| 484 |  |  |  |  |  |  | my %ancestors	= ($cur => 1); | 
| 485 |  |  |  |  |  |  | while ($cur = $type_hierarchy{$cur}) { | 
| 486 |  |  |  |  |  |  | $ancestors{$cur}++; | 
| 487 |  |  |  |  |  |  | return "http://www.w3.org/2001/XMLSchema#$cur" if ($cur eq $rhs); | 
| 488 |  |  |  |  |  |  | } | 
| 489 |  |  |  |  |  |  | $cur	= $rhs; | 
| 490 |  |  |  |  |  |  | while ($cur = $type_hierarchy{$cur}) { | 
| 491 |  |  |  |  |  |  | return "http://www.w3.org/2001/XMLSchema#$cur" if exists $ancestors{$cur}; | 
| 492 |  |  |  |  |  |  | } | 
| 493 |  |  |  |  |  |  | return; | 
| 494 |  |  |  |  |  |  | } | 
| 495 |  |  |  |  |  |  | my $self	= shift; | 
| 496 |  |  |  |  |  |  | my $rhs		= shift; | 
| 497 |  |  |  |  |  |  | my $op		= shift; | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | if ($op =~ m<^[-+*]$>) { | 
| 500 |  |  |  |  |  |  | # return common numeric type | 
| 501 | 7 |  |  | 7 |  | 25 | if (my $type = _lca($self->datatype->value, $rhs->datatype->value)) { | 
| 502 | 7 |  |  |  |  | 10 | return $type; | 
| 503 | 14 |  |  |  |  | 49 | } | 
| 504 |  |  |  |  |  |  | return 'http://www.w3.org/2001/XMLSchema#double'; | 
| 505 | 7 | 100 |  |  |  | 25 | } elsif ($op eq '/') { | 
| 506 | 3 |  |  |  |  | 4 | if ($self->is_integer_type and $rhs->is_integer_type) { | 
| 507 | 3 |  |  |  |  | 7 | # return xsd:decimal if both operands are integers | 
| 508 | 3 |  |  |  |  | 6 | return 'http://www.w3.org/2001/XMLSchema#decimal'; | 
| 509 | 5 |  |  |  |  | 7 | } | 
| 510 | 5 | 50 |  |  |  | 11 | if (my $type = _lca($self->datatype->value, $rhs->datatype->value)) { | 
| 511 |  |  |  |  |  |  | return $type; | 
| 512 | 3 |  |  |  |  | 5 | } | 
| 513 | 3 |  |  |  |  | 5 | return 'http://www.w3.org/2001/XMLSchema#double'; | 
| 514 | 6 | 100 |  |  |  | 23 | } | 
| 515 |  |  |  |  |  |  | die "Unexpected numeric operation in binary_promotion_type: $op"; | 
| 516 | 1 |  |  |  |  | 3 | } | 
| 517 |  |  |  |  |  |  | } | 
| 518 |  |  |  |  |  |  | with 'Attean::API::Literal', 'Attean::API::CanonicalizingLiteral'; | 
| 519 | 21 |  |  | 21 | 0 | 381 | } | 
| 520 | 21 |  |  |  |  | 26 |  | 
| 521 | 21 |  |  |  |  | 25 | use Scalar::Util qw(blessed); | 
| 522 |  |  |  |  |  |  | use AtteanX::SPARQL::Constants; | 
| 523 | 21 | 100 |  |  |  | 80 | use AtteanX::SPARQL::Token; | 
|  |  | 50 |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | use Attean::API::Query; | 
| 525 | 7 | 100 |  |  |  | 115 |  | 
| 526 | 6 |  |  |  |  | 59 | use Moo::Role; | 
| 527 |  |  |  |  |  |  |  | 
| 528 | 1 |  |  |  |  | 6 | with 'Attean::API::Term', 'Attean::API::BlankOrIRI', 'Attean::API::BlankOrIRIOrTriple'; | 
| 529 |  |  |  |  |  |  | ; | 
| 530 | 14 | 50 | 33 |  |  | 44 | with 'Attean::API::SPARQLSerializable'; | 
| 531 |  |  |  |  |  |  |  | 
| 532 | 14 |  |  |  |  | 200 | my $self	= shift; | 
| 533 |  |  |  |  |  |  | my $t	= AtteanX::SPARQL::Token->fast_constructor( BNODE, -1, -1, -1, -1, [$self->value] ); | 
| 534 | 0 | 0 |  |  |  | 0 | return Attean::ListIterator->new( values => [$t], item_type => 'AtteanX::SPARQL::Token' ); | 
| 535 | 0 |  |  |  |  | 0 | } | 
| 536 |  |  |  |  |  |  |  | 
| 537 | 0 |  |  |  |  | 0 | my ($a, $b)	= @_; | 
| 538 |  |  |  |  |  |  | return 1 unless blessed($b); | 
| 539 | 0 |  |  |  |  | 0 | return -1 unless ($b->does('Attean::API::Blank')); | 
| 540 |  |  |  |  |  |  | return ($a->value cmp $b->value); | 
| 541 |  |  |  |  |  |  | } | 
| 542 |  |  |  |  |  |  | } | 
| 543 |  |  |  |  |  |  |  | 
| 544 |  |  |  |  |  |  | use IRI; | 
| 545 |  |  |  |  |  |  | use Scalar::Util qw(blessed); | 
| 546 | 50 |  |  | 50 |  | 415 | use AtteanX::SPARQL::Constants; | 
|  | 50 |  |  |  |  | 125 |  | 
|  | 50 |  |  |  |  | 2524 |  | 
| 547 | 50 |  |  | 50 |  | 335 | use AtteanX::SPARQL::Token; | 
|  | 50 |  |  |  |  | 110 |  | 
|  | 50 |  |  |  |  | 8334 |  | 
| 548 | 50 |  |  | 50 |  | 401 | use Attean::API::Query; | 
|  | 50 |  |  |  |  | 135 |  | 
|  | 50 |  |  |  |  | 1781 |  | 
| 549 | 50 |  |  | 50 |  | 295 |  | 
|  | 50 |  |  |  |  | 130 |  | 
|  | 50 |  |  |  |  | 1312 |  | 
| 550 |  |  |  |  |  |  | use Moo::Role; | 
| 551 | 50 |  |  | 50 |  | 275 |  | 
|  | 50 |  |  |  |  | 119 |  | 
|  | 50 |  |  |  |  | 242 |  | 
| 552 |  |  |  |  |  |  | with 'Attean::API::Term', 'Attean::API::BlankOrIRI', 'Attean::API::BlankOrIRIOrTriple'; | 
| 553 | 1 |  |  | 1 | 1 | 41 | with 'Attean::API::SPARQLSerializable'; | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | my $self	= shift; | 
| 556 |  |  |  |  |  |  | my @tokens; | 
| 557 |  |  |  |  |  |  | if ($self->value eq '') { | 
| 558 |  |  |  |  |  |  | push(@tokens, AtteanX::Parser::Turtle::Token->a); | 
| 559 | 13 |  |  | 13 | 0 | 19 | } else { | 
| 560 | 13 |  |  |  |  | 83 | push(@tokens, AtteanX::SPARQL::Token->fast_constructor( IRI, -1, -1, -1, -1, [$self->value] )); | 
| 561 | 13 |  |  |  |  | 797 | } | 
| 562 |  |  |  |  |  |  | return Attean::ListIterator->new( values => \@tokens, item_type => 'AtteanX::SPARQL::Token' ); | 
| 563 |  |  |  |  |  |  | } | 
| 564 |  |  |  |  |  |  |  | 
| 565 | 3 |  |  | 3 | 1 | 44 | my ($a, $b)	= @_; | 
| 566 | 3 | 50 |  |  |  | 24 | return 1 unless blessed($b); | 
| 567 | 3 | 50 |  |  |  | 9 | return -1 if ($b->does('Attean::API::Literal') or $b->does('Attean::API::Binding')); | 
| 568 | 3 |  |  |  |  | 51 | return 1 unless ($b->does('Attean::API::IRI')); | 
| 569 |  |  |  |  |  |  | return ($a->value cmp $b->value); | 
| 570 |  |  |  |  |  |  | } | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | my $self	= shift; | 
| 573 | 50 |  |  | 50 |  | 25835 | return sprintf('<%s>', $self->__ntriples_string); | 
|  | 50 |  |  |  |  | 97 |  | 
|  | 50 |  |  |  |  | 1480 |  | 
| 574 | 50 |  |  | 50 |  | 271 | } | 
|  | 50 |  |  |  |  | 122 |  | 
|  | 50 |  |  |  |  | 2211 |  | 
| 575 | 50 |  |  | 50 |  | 314 |  | 
|  | 50 |  |  |  |  | 91 |  | 
|  | 50 |  |  |  |  | 6705 |  | 
| 576 | 50 |  |  | 50 |  | 309 | around as_sparql => sub { | 
|  | 50 |  |  |  |  | 129 |  | 
|  | 50 |  |  |  |  | 1073 |  | 
| 577 | 50 |  |  | 50 |  | 300 | my $orig	= shift; | 
|  | 50 |  |  |  |  | 102 |  | 
|  | 50 |  |  |  |  | 1119 |  | 
| 578 |  |  |  |  |  |  | my $self	= shift; | 
| 579 | 50 |  |  | 50 |  | 234 |  | 
|  | 50 |  |  |  |  | 91 |  | 
|  | 50 |  |  |  |  | 203 |  | 
| 580 |  |  |  |  |  |  | if ($self->value eq 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') { | 
| 581 | 1 |  |  | 1 | 1 | 112 | return 'a'; | 
| 582 |  |  |  |  |  |  | } | 
| 583 |  |  |  |  |  |  |  | 
| 584 |  |  |  |  |  |  | return $self->$orig(@_); | 
| 585 |  |  |  |  |  |  | }; | 
| 586 | 244 |  |  | 244 | 0 | 424 | } | 
| 587 | 244 |  |  |  |  | 370 |  | 
| 588 | 244 | 50 |  |  |  | 928 | 1; | 
| 589 | 0 |  |  |  |  | 0 |  | 
| 590 |  |  |  |  |  |  |  | 
| 591 | 244 |  |  |  |  | 1195 | =back | 
| 592 |  |  |  |  |  |  |  | 
| 593 | 244 |  |  |  |  | 14958 | =head1 BUGS | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | Please report any bugs or feature requests to through the GitHub web interface | 
| 596 |  |  |  |  |  |  | at L<https://github.com/kasei/attean/issues>. | 
| 597 | 13 |  |  | 13 | 1 | 19 |  | 
| 598 | 13 | 50 |  |  |  | 34 | =head1 SEE ALSO | 
| 599 | 13 | 50 | 33 |  |  | 28 |  | 
| 600 | 13 | 50 |  |  |  | 539 |  | 
| 601 | 13 |  |  |  |  | 167 |  | 
| 602 |  |  |  |  |  |  | =head1 AUTHOR | 
| 603 |  |  |  |  |  |  |  | 
| 604 |  |  |  |  |  |  | Gregory Todd Williams  C<< <gwilliams@cpan.org> >> | 
| 605 | 427 |  |  | 427 |  | 4734 |  | 
| 606 | 427 |  |  |  |  | 871 | =head1 COPYRIGHT | 
| 607 |  |  |  |  |  |  |  | 
| 608 |  |  |  |  |  |  | Copyright (c) 2014--2022 Gregory Todd Williams. | 
| 609 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it under | 
| 610 |  |  |  |  |  |  | the same terms as Perl itself. | 
| 611 |  |  |  |  |  |  |  | 
| 612 |  |  |  |  |  |  | =cut |