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.018
11              
12             =cut
13              
14             package RDF::Trine::Node::Resource;
15              
16 68     68   25412 use utf8;
  68         793  
  68         365  
17 68     68   1867 use strict;
  68         141  
  68         1236  
18 68     68   306 use warnings;
  68         125  
  68         1714  
19 68     68   306 no warnings 'redefine';
  68         129  
  68         2015  
20 68     68   374 use base qw(RDF::Trine::Node);
  68         155  
  68         4178  
21              
22 68     68   26559 use IRI;
  68         9344239  
  68         15869  
23 68     68   936 use URI 1.52;
  68         2028  
  68         1805  
24 68     68   43513 use Encode;
  68         623399  
  68         5232  
25 68     68   531 use Data::Dumper;
  68         152  
  68         2912  
26 68     68   387 use Scalar::Util qw(blessed reftype refaddr);
  68         143  
  68         3293  
27 68     68   384 use Carp qw(carp croak confess);
  68         146  
  68         4866  
28              
29             ######################################################################
30              
31             our ($VERSION, %sse, %ntriples);
32             BEGIN {
33 68     68   2548 $VERSION = '1.018';
34             }
35              
36             ######################################################################
37              
38 21277     21277   82210 use overload '""' => sub { $_[0]->sse },
39 68     68   404 ;
  68         140  
  68         718  
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 42400 my $class = shift;
58 15844         25588 my $uri = shift;
59 15844         25345 my $base_uri = shift;
60            
61 15844 50       37977 unless (defined($uri)) {
62 0         0 throw RDF::Trine::Error::MethodInvocationError -text => "Resource constructor called with an undefined value";
63             }
64            
65 15844 100       37099 if (defined($base_uri)) {
66 2785 100       9842 if (blessed($base_uri)) {
67 1060 100       4351 if ($base_uri->isa('RDF::Trine::Node::Resource')) {
68 975         2176 $base_uri = IRI->new( $base_uri->uri_value );
69             }
70             } else {
71 1725         29458 $base_uri = IRI->new($base_uri);
72             }
73 2785         863519 my $iri = IRI->new( value => $uri, base => $base_uri );
74 2785         826711 $uri = $iri->abs;
75             }
76 15844         1114090 utf8::upgrade($uri);
77            
78 15844 50       53425 if ($uri eq &RDF::Trine::NIL_GRAPH) {
79 0         0 return RDF::Trine::Node::Nil->new();
80             }
81            
82 15844 50       56274 if ($uri =~ /([<>" {}|\\^`])/) {
83 0         0 throw RDF::Trine::Error -text => sprintf("Bad IRI character: '%s' (0x%x)", $1, ord($1));
84             }
85            
86 15844         80710 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 46634     46634 1 82708 my $self = shift;
97 46634         195816 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         37 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 50531 my $self = shift;
119 687 100       1885 if (@_) {
120 1         3 $self->[1] = shift;
121 1         4 delete $sse{ refaddr($self) };
122 1         4 delete $ntriples{ refaddr($self) };
123             }
124 687         3828 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 36141     36141 1 55262 my $self = shift;
135 36141         51268 my $context = shift;
136            
137 36141 100       77326 if ($context) {
138 2         5 my $uri = $self->uri_value;
139 2   50     9 my $ns = $context->{namespaces} || {};
140 2         8 my %ns = %$ns;
141 2         7 foreach my $k (keys %ns) {
142 2         5 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 36140         74203 my $ra = refaddr($self);
151 36140 100       81187 if ($sse{ $ra }) {
152 27504         80285 return $sse{ $ra };
153             } else {
154 8636         21267 my $string = URI->new( $self->uri_value )->canonical;
155 8636         1607350 my $sse = '<' . $string . '>';
156 8636         61095 $sse{ $ra } = $sse;
157 8636         35577 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 36262 my $self = shift;
173 23488         47857 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 5113 my $self = shift;
185 3304         4797 my $context = shift;
186 3304         7354 my $ra = refaddr($self);
187 3304 100       7998 if ($ntriples{ $ra }) {
188 204         766 return $ntriples{ $ra };
189             } else {
190 3100         6813 my $uri = $self->uri_value;
191 3100         9912 $uri = URI->new($uri)->as_iri;
192 3100         293254 my @chars = split(//, $uri);
193 3100         5848 my $string = '';
194 3100         8100 while (scalar(@chars)) {
195 107571         157747 my $c = shift(@chars);
196 107571         144577 my $o = ord($c);
197 107571 50       501530 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         74512 $string .= $c;
215             } elsif ($o == 0x5C) {
216 0         0 $string .= "\\";
217             } elsif ($o < 0x7E) {
218 70706         143695 $string .= $c;
219             } elsif ($o < 0xFFFF) {
220 167         519 $string .= sprintf("\\u%04X", $o);
221             } else {
222 8         27 $string .= sprintf("\\U%08X", $o);
223             }
224             }
225 3100         7581 my $ntriples = '<' . $string . '>';
226 3100         7281 $ntriples{ $ra } = $ntriples;
227 3100         14434 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 12501 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 2153 my $self = shift;
249 1219         1923 my $node = shift;
250 1219 100       2949 return 0 unless defined($node);
251 1182 100       4235 return 1 if (refaddr($self) == refaddr($node));
252 1128 100 66     8152 return 0 unless (blessed($node) and $node->isa('RDF::Trine::Node::Resource'));
253            
254 1112         2988 my $uri1 = URI->new($self->uri_value)->as_iri;
255 1112         104560 my $uri2 = URI->new($node->uri_value)->as_iri;
256 1112         80797 return ($uri1 eq $uri2);
257             }
258              
259             # called to compare two nodes of the same type
260             sub _compare {
261 1462     1462   2172 my $a = shift;
262 1462         2104 my $b = shift;
263 1462         2620 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 1463 my $p = shift;
275 263         599 my $uri = $p->uri_value;
276              
277 263   66     1065 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     1195 our $r_PN_CHARS_U ||= qr/(_|${r_PN_CHARS_BASE})/;
279 263   66     1177 our $r_PN_CHARS ||= qr/${r_PN_CHARS_U}|-|[0-9]|\x{00B7}|[\x{0300}-\x{036F}]|[\x{203F}-\x{2040}]/;
280 263   66     1604 our $r_PN_LOCAL ||= qr/((${r_PN_CHARS_U})((${r_PN_CHARS}|[.])*${r_PN_CHARS})?)/;
281 263 100       36467 if ($uri =~ m/${r_PN_LOCAL}$/) {
282 252         791 my $ln = $1;
283 252         900 my $ns = substr($uri, 0, length($uri)-length($ln));
284 252         1274 return ($ns, $ln);
285             } else {
286 11         97 throw RDF::Trine::Error -text => "Can't turn IRI $uri into a QName.";
287             }
288             }
289              
290             sub DESTROY {
291 15799     15799   753461 my $self = shift;
292 15799         42886 delete $sse{ refaddr($self) };
293 15799         79556 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