File Coverage

blib/lib/RDF/Trine/Node/Resource.pm
Criterion Covered Total %
statement 129 141 91.4
branch 42 54 77.7
condition 11 17 64.7
subroutine 26 26 100.0
pod 10 10 100.0
total 218 248 87.9


line stmt bran cond sub pod time code
1             # RDF::Trine::Node::Resource
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Trine::Node::Resource - RDF Node class for IRI resources
7              
8             =head1 VERSION
9              
10             This document describes RDF::Trine::Node::Resource version 1.017
11              
12             =cut
13              
14             package RDF::Trine::Node::Resource;
15              
16 68     68   25306 use utf8;
  68         799  
  68         383  
17 68     68   1924 use strict;
  68         144  
  68         1168  
18 68     68   286 use warnings;
  68         136  
  68         1660  
19 68     68   293 no warnings 'redefine';
  68         133  
  68         1940  
20 68     68   315 use base qw(RDF::Trine::Node);
  68         152  
  68         4473  
21              
22 68     68   26380 use IRI;
  68         9505241  
  68         16494  
23 68     68   1004 use URI 1.52;
  68         2152  
  68         1802  
24 68     68   43961 use Encode;
  68         625787  
  68         5439  
25 68     68   543 use Data::Dumper;
  68         153  
  68         3241  
26 68     68   405 use Scalar::Util qw(blessed reftype refaddr);
  68         147  
  68         3659  
27 68     68   384 use Carp qw(carp croak confess);
  68         145  
  68         5379  
28              
29             ######################################################################
30              
31             our ($VERSION, %sse, %ntriples);
32             BEGIN {
33 68     68   2714 $VERSION = '1.017';
34             }
35              
36             ######################################################################
37              
38 21277     21277   84163 use overload '""' => sub { $_[0]->sse },
39 68     68   407 ;
  68         146  
  68         799  
40              
41             =head1 METHODS
42              
43             Beyond the methods documented below, this class inherits methods from the
44             L<RDF::Trine::Node> class.
45              
46             =over 4
47              
48             =cut
49              
50             =item C<new ( $iri, [ $base_uri ] )>
51              
52             Returns a new Resource structure.
53              
54             =cut
55              
56             sub new {
57 15844     15844 1 43882 my $class = shift;
58 15844         26437 my $uri = shift;
59 15844         26234 my $base_uri = shift;
60            
61 15844 50       39745 unless (defined($uri)) {
62 0         0 throw RDF::Trine::Error::MethodInvocationError -text => "Resource constructor called with an undefined value";
63             }
64            
65 15844 100       39998 if (defined($base_uri)) {
66 2785 100       10125 if (blessed($base_uri)) {
67 1060 100       4647 if ($base_uri->isa('RDF::Trine::Node::Resource')) {
68 975         2597 $base_uri = IRI->new( $base_uri->uri_value );
69             }
70             } else {
71 1725         30491 $base_uri = IRI->new($base_uri);
72             }
73 2785         919027 my $iri = IRI->new( value => $uri, base => $base_uri );
74 2785         859565 $uri = $iri->abs;
75             }
76 15844         1147814 utf8::upgrade($uri);
77            
78 15844 50       55596 if ($uri eq &RDF::Trine::NIL_GRAPH) {
79 0         0 return RDF::Trine::Node::Nil->new();
80             }
81            
82 15844 50       58330 if ($uri =~ /([<>" {}|\\^`])/) {
83 0         0 throw RDF::Trine::Error -text => sprintf("Bad IRI character: '%s' (0x%x)", $1, ord($1));
84             }
85            
86 15844         83996 return bless( [ 'URI', $uri ], $class );
87             }
88              
89             =item C<< uri_value >>
90              
91             Returns the URI/IRI value of this resource.
92              
93             =cut
94              
95             sub uri_value {
96 46632     46632 1 86149 my $self = shift;
97 46632         211190 return $self->[1];
98             }
99              
100             =item C<< value >>
101              
102             Returns the URI/IRI value.
103              
104             =cut
105              
106             sub value {
107 11     11 1 26 my $self = shift;
108 11         36 return $self->uri_value;
109             }
110              
111             =item C<< uri ( $uri ) >>
112              
113             Returns the URI value of this resource, optionally updating the URI.
114              
115             =cut
116              
117             sub uri {
118 687     687 1 62502 my $self = shift;
119 687 100       2222 if (@_) {
120 1         3 $self->[1] = shift;
121 1         6 delete $sse{ refaddr($self) };
122 1         3 delete $ntriples{ refaddr($self) };
123             }
124 687         4144 return $self->[1];
125             }
126              
127             =item C<< sse >>
128              
129             Returns the SSE string for this resource.
130              
131             =cut
132              
133             sub sse {
134 36144     36144 1 55920 my $self = shift;
135 36144         53458 my $context = shift;
136            
137 36144 100       77681 if ($context) {
138 2         7 my $uri = $self->uri_value;
139 2   50     8 my $ns = $context->{namespaces} || {};
140 2         8 my %ns = %$ns;
141 2         7 foreach my $k (keys %ns) {
142 2         4 my $v = $ns{ $k };
143 2 100       10 if (index($uri, $v) == 0) {
144 1         5 my $qname = join(':', $k, substr($uri, length($v)));
145 1         6 return $qname;
146             }
147             }
148             }
149            
150 36143         75625 my $ra = refaddr($self);
151 36143 100       85570 if ($sse{ $ra }) {
152 27507         85433 return $sse{ $ra };
153             } else {
154 8636         22112 my $string = URI->new( $self->uri_value )->canonical;
155 8636         1660415 my $sse = '<' . $string . '>';
156 8636         63760 $sse{ $ra } = $sse;
157 8636         37722 return $sse;
158             }
159            
160             # my $string = $uri;
161             # my $escaped = $self->_unicode_escape( $string );
162             # return '<' . $escaped . '>';
163             }
164              
165             =item C<< as_string >>
166              
167             Returns a string representation of the node.
168              
169             =cut
170              
171             sub as_string {
172 23488     23488 1 39649 my $self = shift;
173 23488         51776 return '<' . $self->uri_value . '>';
174             }
175              
176             =item C<< as_ntriples >>
177              
178             Returns the node in a string form suitable for NTriples serialization.
179             If the IRI contains punycode, it will be decoded and serialized as unicode codepoints.
180              
181             =cut
182              
183             sub as_ntriples {
184 3304     3304 1 5631 my $self = shift;
185 3304         5510 my $context = shift;
186 3304         7656 my $ra = refaddr($self);
187 3304 100       8407 if ($ntriples{ $ra }) {
188 204         847 return $ntriples{ $ra };
189             } else {
190 3100         6986 my $uri = $self->uri_value;
191 3100         11146 $uri = URI->new($uri)->as_iri;
192 3100         314196 my @chars = split(//, $uri);
193 3100         6284 my $string = '';
194 3100         8866 while (scalar(@chars)) {
195 107571         160977 my $c = shift(@chars);
196 107571         153334 my $o = ord($c);
197 107571 50       514432 if ($o < 0x8) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
198 0         0 $string .= sprintf("\\u%04X", $o);
199             } elsif ($o == 0x9) {
200 0         0 $string .= "\\t";
201             } elsif ($o == 0xA) {
202 0         0 $string .= "\\n";
203             } elsif ($o < 0xC) {
204 0         0 $string .= sprintf("\\u%04X", $o);
205             } elsif ($o == 0xD) {
206 0         0 $string .= "\\r";
207             } elsif ($o < 0x1F) {
208 0         0 $string .= sprintf("\\u%04X", $o);
209             } elsif ($o < 0x21) {
210 0         0 $string .= $c;
211             } elsif ($o == 0x22) {
212 0         0 $string .= "\"";
213             } elsif ($o < 0x5B) {
214 36690         77765 $string .= $c;
215             } elsif ($o == 0x5C) {
216 0         0 $string .= "\\";
217             } elsif ($o < 0x7E) {
218 70706         149052 $string .= $c;
219             } elsif ($o < 0xFFFF) {
220 167         563 $string .= sprintf("\\u%04X", $o);
221             } else {
222 8         27 $string .= sprintf("\\U%08X", $o);
223             }
224             }
225 3100         8544 my $ntriples = '<' . $string . '>';
226 3100         8116 $ntriples{ $ra } = $ntriples;
227 3100         16282 return $ntriples;
228             }
229             }
230              
231             =item C<< type >>
232              
233             Returns the type string of this node.
234              
235             =cut
236              
237             sub type {
238 6358     6358 1 14622 return 'URI';
239             }
240              
241             =item C<< equal ( $node ) >>
242              
243             Returns true if the two nodes are equal, false otherwise.
244              
245             =cut
246              
247             sub equal {
248 1219     1219 1 2325 my $self = shift;
249 1219         1904 my $node = shift;
250 1219 100       3087 return 0 unless defined($node);
251 1182 100       4437 return 1 if (refaddr($self) == refaddr($node));
252 1128 100 66     8133 return 0 unless (blessed($node) and $node->isa('RDF::Trine::Node::Resource'));
253            
254 1112         3016 my $uri1 = URI->new($self->uri_value)->as_iri;
255 1112         107023 my $uri2 = URI->new($node->uri_value)->as_iri;
256 1112         85069 return ($uri1 eq $uri2);
257             }
258              
259             # called to compare two nodes of the same type
260             sub _compare {
261 1461     1461   2505 my $a = shift;
262 1461         2369 my $b = shift;
263 1461         3118 return ($a->uri_value cmp $b->uri_value);
264             }
265              
266             =item C<< qname >>
267              
268             If the IRI can be split into a namespace and local part for construction of a
269             QName, returns a list containing these two parts. Otherwise throws an exception.
270              
271             =cut
272              
273             sub qname {
274 263     263 1 1316 my $p = shift;
275 263         701 my $uri = $p->uri_value;
276              
277 263   66     888 our $r_PN_CHARS_BASE ||= qr/([A-Z]|[a-z]|[\x{00C0}-\x{00D6}]|[\x{00D8}-\x{00F6}]|[\x{00F8}-\x{02FF}]|[\x{0370}-\x{037D}]|[\x{037F}-\x{1FFF}]|[\x{200C}-\x{200D}]|[\x{2070}-\x{218F}]|[\x{2C00}-\x{2FEF}]|[\x{3001}-\x{D7FF}]|[\x{F900}-\x{FDCF}]|[\x{FDF0}-\x{FFFD}]|[\x{10000}-\x{EFFFF}])/;
278 263   66     1283 our $r_PN_CHARS_U ||= qr/(_|${r_PN_CHARS_BASE})/;
279 263   66     1232 our $r_PN_CHARS ||= qr/${r_PN_CHARS_U}|-|[0-9]|\x{00B7}|[\x{0300}-\x{036F}]|[\x{203F}-\x{2040}]/;
280 263   66     1613 our $r_PN_LOCAL ||= qr/((${r_PN_CHARS_U})((${r_PN_CHARS}|[.])*${r_PN_CHARS})?)/;
281 263 100       37068 if ($uri =~ m/${r_PN_LOCAL}$/) {
282 252         905 my $ln = $1;
283 252         1057 my $ns = substr($uri, 0, length($uri)-length($ln));
284 252         1317 return ($ns, $ln);
285             } else {
286 11         130 throw RDF::Trine::Error -text => "Can't turn IRI $uri into a QName.";
287             }
288             }
289              
290             sub DESTROY {
291 15799     15799   901099 my $self = shift;
292 15799         51514 delete $sse{ refaddr($self) };
293 15799         98809 delete $ntriples{ refaddr($self) };
294             }
295              
296             1;
297              
298             __END__
299              
300             =back
301              
302             =head1 BUGS
303              
304             Please report any bugs or feature requests to through the GitHub web interface
305             at L<https://github.com/kasei/perlrdf/issues>.
306              
307             =head1 AUTHOR
308              
309             Gregory Todd Williams C<< <gwilliams@cpan.org> >>
310              
311             =head1 COPYRIGHT
312              
313             Copyright (c) 2006-2012 Gregory Todd Williams. This
314             program is free software; you can redistribute it and/or modify it under
315             the same terms as Perl itself.
316              
317             =cut