| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # RDF::Trine::Parser::RDFJSON | 
| 2 |  |  |  |  |  |  | # ----------------------------------------------------------------------------- | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | =head1 NAME | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | RDF::Trine::Parser::RDFJSON - RDF/JSON RDF Parser | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | =head1 VERSION | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | This document describes RDF::Trine::Parser::RDFJSON version 1.018 | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | use RDF::Trine::Parser; | 
| 15 |  |  |  |  |  |  | my $parser	= RDF::Trine::Parser->new( 'RDF/JSON' ); | 
| 16 |  |  |  |  |  |  | $parser->parse_into_model( $base_uri, $data, $model ); | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | ... | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | =head1 METHODS | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | Beyond the methods documented below, this class inherits methods from the | 
| 25 |  |  |  |  |  |  | L<RDF::Trine::Parser> class. | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | =over 4 | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | =cut | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | package RDF::Trine::Parser::RDFJSON; | 
| 32 |  |  |  |  |  |  |  | 
| 33 | 68 |  |  | 68 |  | 444 | use strict; | 
|  | 68 |  |  |  |  | 157 |  | 
|  | 68 |  |  |  |  | 1762 |  | 
| 34 | 68 |  |  | 68 |  | 349 | use warnings; | 
|  | 68 |  |  |  |  | 151 |  | 
|  | 68 |  |  |  |  | 1733 |  | 
| 35 | 68 |  |  | 68 |  | 328 | no warnings 'redefine'; | 
|  | 68 |  |  |  |  | 151 |  | 
|  | 68 |  |  |  |  | 1986 |  | 
| 36 | 68 |  |  | 68 |  | 346 | no warnings 'once'; | 
|  | 68 |  |  |  |  | 150 |  | 
|  | 68 |  |  |  |  | 1634 |  | 
| 37 | 68 |  |  | 68 |  | 333 | use base qw(RDF::Trine::Parser); | 
|  | 68 |  |  |  |  | 150 |  | 
|  | 68 |  |  |  |  | 4552 |  | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 68 |  |  | 68 |  | 432 | use URI; | 
|  | 68 |  |  |  |  | 203 |  | 
|  | 68 |  |  |  |  | 1312 |  | 
| 40 | 68 |  |  | 68 |  | 333 | use Log::Log4perl; | 
|  | 68 |  |  |  |  | 153 |  | 
|  | 68 |  |  |  |  | 490 |  | 
| 41 |  |  |  |  |  |  |  | 
| 42 | 68 |  |  | 68 |  | 4306 | use RDF::Trine qw(literal); | 
|  | 68 |  |  |  |  | 165 |  | 
|  | 68 |  |  |  |  | 2987 |  | 
| 43 | 68 |  |  | 68 |  | 394 | use RDF::Trine::Statement; | 
|  | 68 |  |  |  |  | 161 |  | 
|  | 68 |  |  |  |  | 1326 |  | 
| 44 | 68 |  |  | 68 |  | 334 | use RDF::Trine::Namespace; | 
|  | 68 |  |  |  |  | 150 |  | 
|  | 68 |  |  |  |  | 422 |  | 
| 45 | 68 |  |  | 68 |  | 384 | use RDF::Trine::Node; | 
|  | 68 |  |  |  |  | 163 |  | 
|  | 68 |  |  |  |  | 2294 |  | 
| 46 | 68 |  |  | 68 |  | 401 | use RDF::Trine::Error qw(:try); | 
|  | 68 |  |  |  |  | 157 |  | 
|  | 68 |  |  |  |  | 434 |  | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 68 |  |  | 68 |  | 8965 | use Scalar::Util qw(blessed looks_like_number); | 
|  | 68 |  |  |  |  | 159 |  | 
|  | 68 |  |  |  |  | 3178 |  | 
| 49 | 68 |  |  | 68 |  | 425 | use JSON; | 
|  | 68 |  |  |  |  | 166 |  | 
|  | 68 |  |  |  |  | 583 |  | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | our ($VERSION, $rdf, $xsd); | 
| 52 |  |  |  |  |  |  | our ($r_boolean, $r_comment, $r_decimal, $r_double, $r_integer, $r_language, $r_lcharacters, $r_line, $r_nameChar_extra, $r_nameStartChar_minus_underscore, $r_scharacters, $r_ucharacters, $r_booltest, $r_nameStartChar, $r_nameChar, $r_prefixName, $r_qname, $r_resource_test, $r_nameChar_test); | 
| 53 |  |  |  |  |  |  | BEGIN { | 
| 54 | 68 |  |  | 68 |  | 17843 | $VERSION				= '1.018'; | 
| 55 | 68 |  |  |  |  | 194 | $RDF::Trine::Parser::parser_names{ 'rdfjson' }	= __PACKAGE__; | 
| 56 | 68 |  |  |  |  | 185 | foreach my $ext (qw(json js)) { | 
| 57 | 136 |  |  |  |  | 362 | $RDF::Trine::Parser::file_extensions{ $ext }	= __PACKAGE__; | 
| 58 |  |  |  |  |  |  | } | 
| 59 | 68 |  |  |  |  | 212 | my $class										= __PACKAGE__; | 
| 60 | 68 |  |  |  |  | 174 | $RDF::Trine::Parser::canonical_media_types{ $class }	= 'application/json'; | 
| 61 | 68 |  |  |  |  | 169 | foreach my $type (qw(application/json application/x-rdf+json)) { | 
| 62 | 136 |  |  |  |  | 45113 | $RDF::Trine::Parser::media_types{ $type }	= __PACKAGE__; | 
| 63 |  |  |  |  |  |  | } | 
| 64 |  |  |  |  |  |  | } | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | =item C<< new >> | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | Returns a new RDFJSON parser. | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | =cut | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | sub new { | 
| 73 | 2 |  |  | 2 | 1 | 6 | my $class	= shift; | 
| 74 | 2 |  |  |  |  | 9 | my %args	= @_; | 
| 75 | 2 |  |  |  |  | 5 | my $prefix	= ''; | 
| 76 | 2 | 50 |  |  |  | 9 | if (defined($args{ bnode_prefix })) { | 
| 77 | 0 |  |  |  |  | 0 | $prefix	= $args{ bnode_prefix }; | 
| 78 |  |  |  |  |  |  | } else { | 
| 79 | 2 |  |  |  |  | 15 | $prefix	= $class->new_bnode_prefix(); | 
| 80 |  |  |  |  |  |  | } | 
| 81 | 2 |  |  |  |  | 13 | my $self	= bless({ | 
| 82 |  |  |  |  |  |  | bindings		=> {}, | 
| 83 |  |  |  |  |  |  | bnode_id		=> 0, | 
| 84 |  |  |  |  |  |  | bnode_prefix	=> $prefix, | 
| 85 |  |  |  |  |  |  | @_ | 
| 86 |  |  |  |  |  |  | }, $class); | 
| 87 | 2 |  |  |  |  | 10 | return $self; | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | =item C<< parse_into_model ( $base_uri, $data, $model [, context => $context] ) >> | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | Parses the bytes in C<< $data >>, using the given C<< $base_uri >>. For each RDF | 
| 93 |  |  |  |  |  |  | statement parsed, will call C<< $model->add_statement( $statement ) >>. | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | =cut | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | sub parse_into_model { | 
| 98 | 2 |  |  | 2 | 1 | 14 | my $proto	= shift; | 
| 99 | 2 | 50 |  |  |  | 11 | my $self	= blessed($proto) ? $proto : $proto->new(); | 
| 100 | 2 |  |  |  |  | 7 | my $uri		= shift; | 
| 101 | 2 | 50 | 33 |  |  | 10 | if (blessed($uri) and $uri->isa('RDF::Trine::Node::Resource')) { | 
| 102 | 0 |  |  |  |  | 0 | $uri	= $uri->uri_value; | 
| 103 |  |  |  |  |  |  | } | 
| 104 | 2 |  |  |  |  | 6 | my $input	= shift; | 
| 105 | 2 |  |  |  |  | 5 | my $model	= shift; | 
| 106 | 2 |  |  |  |  | 7 | my %args	= @_; | 
| 107 | 2 |  |  |  |  | 5 | my $context	= $args{'context'}; | 
| 108 | 2 |  |  |  |  | 5 | my $opts	= $args{'json_opts'}; | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | my $handler	= sub { | 
| 111 | 4 |  |  | 4 |  | 8 | my $st	= shift; | 
| 112 | 4 | 50 |  |  |  | 10 | if ($context) { | 
| 113 | 0 |  |  |  |  | 0 | my $quad	= RDF::Trine::Statement::Quad->new( $st->nodes, $context ); | 
| 114 | 0 |  |  |  |  | 0 | $model->add_statement( $quad ); | 
| 115 |  |  |  |  |  |  | } else { | 
| 116 | 4 |  |  |  |  | 60 | $model->add_statement( $st ); | 
| 117 |  |  |  |  |  |  | } | 
| 118 | 2 |  |  |  |  | 12 | }; | 
| 119 | 2 |  |  |  |  | 9 | return $self->parse( $uri, $input, $handler, $opts ); | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | =item C<< parse ( $base_uri, $rdf, \&handler ) >> | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | Parses the bytes in C<< $data >>, using the given C<< $base_uri >>. Calls the | 
| 125 |  |  |  |  |  |  | C<< triple >> method for each RDF triple parsed. This method does nothing by | 
| 126 |  |  |  |  |  |  | default, but can be set by using one of the default C<< parse_* >> methods. | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | =cut | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | sub parse { | 
| 131 | 2 |  |  | 2 | 1 | 5 | my $self	= shift; | 
| 132 | 2 |  |  |  |  | 5 | my $uri		= shift; | 
| 133 | 2 |  |  |  |  | 4 | my $input	= shift; | 
| 134 | 2 |  |  |  |  | 6 | my $handler	= shift; | 
| 135 | 2 |  |  |  |  | 4 | my $opts	= shift; | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 2 |  |  |  |  | 7 | my $index	= eval { from_json($input, $opts) }; | 
|  | 2 |  |  |  |  | 12 |  | 
| 138 | 2 | 50 |  |  |  | 77 | if ($@) { | 
| 139 | 0 |  |  |  |  | 0 | throw RDF::Trine::Error::ParserError -text => "$@"; | 
| 140 |  |  |  |  |  |  | } | 
| 141 |  |  |  |  |  |  |  | 
| 142 | 2 |  |  |  |  | 10 | foreach my $s (keys %$index) { | 
| 143 |  |  |  |  |  |  | my $ts = ( $s =~ /^_:(.*)$/ ) ? | 
| 144 | 2 | 100 |  |  |  | 29 | RDF::Trine::Node::Blank->new($self->{bnode_prefix} . $1) : | 
| 145 |  |  |  |  |  |  | RDF::Trine::Node::Resource->new($s, $uri); | 
| 146 |  |  |  |  |  |  |  | 
| 147 | 2 |  |  |  |  | 5 | foreach my $p (keys %{ $index->{$s} }) { | 
|  | 2 |  |  |  |  | 9 |  | 
| 148 | 2 |  |  |  |  | 8 | my $tp = RDF::Trine::Node::Resource->new($p, $uri); | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 2 |  |  |  |  | 5 | foreach my $O (@{ $index->{$s}->{$p} }) { | 
|  | 2 |  |  |  |  | 7 |  | 
| 151 | 4 |  |  |  |  | 5 | my $to; | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | # $O should be a hashref, but we can do a little error-correcting. | 
| 154 | 4 | 100 |  |  |  | 13 | unless (ref $O) { | 
| 155 | 1 | 50 |  |  |  | 5 | if ($O =~ /^_:/) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 156 | 1 |  |  |  |  | 6 | $O = { 'value'=>$O, 'type'=>'bnode' }; | 
| 157 |  |  |  |  |  |  | } elsif ($O =~ /^[a-z0-9._\+-]{1,12}:\S+$/i) { | 
| 158 | 0 |  |  |  |  | 0 | $O = { 'value'=>$O, 'type'=>'uri' }; | 
| 159 |  |  |  |  |  |  | } elsif ($O =~ /^(.*)\@([a-z]{2})$/) { | 
| 160 | 0 |  |  |  |  | 0 | $O = { 'value'=>$1, 'type'=>'literal', 'lang'=>$2 }; | 
| 161 |  |  |  |  |  |  | } else { | 
| 162 | 0 |  |  |  |  | 0 | $O = { 'value'=>$O, 'type'=>'literal' }; | 
| 163 |  |  |  |  |  |  | } | 
| 164 |  |  |  |  |  |  | } | 
| 165 |  |  |  |  |  |  |  | 
| 166 | 4 | 100 |  |  |  | 15 | if (lc $O->{'type'} eq 'literal') { | 
| 167 |  |  |  |  |  |  | $to = RDF::Trine::Node::Literal->new( | 
| 168 | 2 |  |  |  |  | 16 | $O->{'value'}, $O->{'lang'}, $O->{'datatype'}); | 
| 169 |  |  |  |  |  |  | } else { | 
| 170 |  |  |  |  |  |  | $to = ( $O->{'value'} =~ /^_:(.*)$/ ) ? | 
| 171 |  |  |  |  |  |  | RDF::Trine::Node::Blank->new($self->{bnode_prefix} . $1) : | 
| 172 | 2 | 100 |  |  |  | 14 | RDF::Trine::Node::Resource->new($O->{'value'}, $uri); | 
| 173 |  |  |  |  |  |  | } | 
| 174 |  |  |  |  |  |  |  | 
| 175 | 4 | 50 | 33 |  |  | 91 | if ( $ts && $tp && $to ) { | 
|  |  |  | 33 |  |  |  |  | 
| 176 | 4 | 50 |  |  |  | 17 | if ($self->{canonicalize}) { | 
| 177 | 0 | 0 | 0 |  |  | 0 | if ($to->isa('RDF::Trine::Node::Literal') and $to->has_datatype) { | 
| 178 | 0 |  |  |  |  | 0 | my $value	= $to->literal_value; | 
| 179 | 0 |  |  |  |  | 0 | my $dt		= $to->literal_datatype; | 
| 180 | 0 |  |  |  |  | 0 | my $canon	= RDF::Trine::Node::Literal->canonicalize_literal_value( $value, $dt, 1 ); | 
| 181 | 0 |  |  |  |  | 0 | $to	= literal( $canon, undef, $dt ); | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  | } | 
| 184 | 4 |  |  |  |  | 19 | my $st = RDF::Trine::Statement->new($ts, $tp, $to); | 
| 185 | 4 |  |  |  |  | 10 | $handler->($st); | 
| 186 |  |  |  |  |  |  | } | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  | } | 
| 190 |  |  |  |  |  |  |  | 
| 191 | 2 |  |  |  |  | 16 | return; | 
| 192 |  |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | 1; | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | __END__ | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | =back | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | =head1 BUGS | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | Please report any bugs or feature requests to through the GitHub web interface | 
| 204 |  |  |  |  |  |  | at L<https://github.com/kasei/perlrdf/issues>. | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | =head1 AUTHOR | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | Toby Inkster <tobyink@cpan.org> | 
| 209 |  |  |  |  |  |  | Gregory Williams <gwilliams@cpan.org> | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | =head1 COPYRIGHT | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | Copyright (c) 2006-2012 Gregory Todd Williams. This | 
| 214 |  |  |  |  |  |  | program is free software; you can redistribute it and/or modify it under | 
| 215 |  |  |  |  |  |  | the same terms as Perl itself. | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | =cut |