line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package RDF::aREF::Decoder; |
2
|
10
|
|
|
10
|
|
273504
|
use strict; |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
293
|
|
3
|
10
|
|
|
10
|
|
44
|
use warnings; |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
208
|
|
4
|
10
|
|
|
10
|
|
90
|
use v5.10; |
|
10
|
|
|
|
|
32
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.27'; |
7
|
|
|
|
|
|
|
|
8
|
10
|
|
|
10
|
|
3658
|
use RDF::NS; |
|
10
|
|
|
|
|
202440
|
|
|
10
|
|
|
|
|
294
|
|
9
|
10
|
|
|
10
|
|
70
|
use Carp qw(croak carp); |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
461
|
|
10
|
10
|
|
|
10
|
|
54
|
use Scalar::Util qw(refaddr reftype blessed); |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
432
|
|
11
|
|
|
|
|
|
|
|
12
|
10
|
|
|
10
|
|
52
|
use parent 'Exporter'; |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
74
|
|
13
|
|
|
|
|
|
|
our @EXPORT_OK = qw(prefix localName qName blankNode blankNodeIdentifier |
14
|
|
|
|
|
|
|
IRIlike languageString languageTag datatypeString); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our ($PREFIX, $NAME); |
17
|
|
|
|
|
|
|
BEGIN { |
18
|
10
|
|
|
10
|
|
1068
|
my $nameStartChar = 'A-Z_a-z\N{U+00C0}-\N{U+00D6}\N{U+00D8}-\N{U+00F6}\N{U+00F8}-\N{U+02FF}\N{U+0370}-\N{U+037D}\N{U+037F}-\N{U+1FFF}\N{U+200C}-\N{U+200D}\N{U+2070}-\N{U+218F}\N{U+2C00}-\N{U+2FEF}\N{U+3001}-\N{U+D7FF}\N{U+F900}-\N{U+FDCF}\N{U+FDF0}-\N{U+FFFD}\N{U+10000}-\N{U+EFFFF}'; |
19
|
10
|
|
|
|
|
29
|
my $nameChar = $nameStartChar.'0-9\-\.\N{U+00B7}\N{U+0300}-\N{U+036F}\N{U+203F}-\N{U+2040}'; |
20
|
10
|
|
|
|
|
30
|
our $PREFIX = '[a-z][a-z0-9]*'; |
21
|
10
|
|
|
|
|
367
|
our $NAME = "[$nameStartChar][$nameChar]*"; |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
|
24
|
10
|
|
|
10
|
|
68
|
use constant localName => qr/^$NAME$/; |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
1158
|
|
25
|
10
|
|
|
10
|
|
58
|
use constant prefix => qr/^$PREFIX$/; |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
837
|
|
26
|
10
|
|
|
10
|
|
59
|
use constant qName => qr/^($PREFIX)_($NAME)$/; |
|
10
|
|
|
|
|
25
|
|
|
10
|
|
|
|
|
1206
|
|
27
|
10
|
|
|
10
|
|
67
|
use constant blankNodeIdentifier => qr/^([a-zA-Z0-9]+)$/; |
|
10
|
|
|
|
|
15
|
|
|
10
|
|
|
|
|
670
|
|
28
|
10
|
|
|
10
|
|
69
|
use constant blankNode => qr/^_:([a-zA-Z0-9]+)$/; |
|
10
|
|
|
|
|
36
|
|
|
10
|
|
|
|
|
674
|
|
29
|
10
|
|
|
10
|
|
62
|
use constant IRIlike => qr/^[a-z][a-z0-9+.-]*:/; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
959
|
|
30
|
10
|
|
|
10
|
|
63
|
use constant languageString => qr/^(.*)@([a-z]{2,8}(-[a-z0-9]{1,8})*)$/i; |
|
10
|
|
|
|
|
62
|
|
|
10
|
|
|
|
|
824
|
|
31
|
10
|
|
|
10
|
|
80
|
use constant languageTag => qr/^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i; |
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
735
|
|
32
|
10
|
|
|
|
|
1193
|
use constant datatypeString => qr/^(.*?)[\^] |
33
|
10
|
|
|
10
|
|
56
|
((($PREFIX)?_($NAME))|<([a-z][a-z0-9+.-]*:.*)>)$/x; |
|
10
|
|
|
|
|
17
|
|
34
|
|
|
|
|
|
|
|
35
|
10
|
|
|
10
|
|
73
|
use constant explicitIRIlike => qr/^<(.+)>$/; |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
456
|
|
36
|
10
|
|
|
10
|
|
52
|
use constant xsd_string => 'http://www.w3.org/2001/XMLSchema#string'; |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
20694
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub new { |
39
|
120
|
|
|
120
|
0
|
115603
|
my ($class, %options) = @_; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my $self = bless { |
42
|
|
|
|
|
|
|
ns => $options{ns}, |
43
|
|
|
|
|
|
|
complain => $options{complain} // 1, |
44
|
|
|
|
|
|
|
strict => $options{strict} // 0, |
45
|
|
|
|
|
|
|
null => $options{null}, # undef by default |
46
|
|
|
|
|
|
|
bnode_prefix => $options{bnode_prefix} || 'b', |
47
|
120
|
|
100
|
|
|
1944
|
bnode_count => $options{bnode_count} || 0, |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
48
|
|
|
|
|
|
|
bnode_map => { }, |
49
|
|
|
|
|
|
|
}, $class; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# facilitate use of this module together with RDF::Trine |
52
|
120
|
|
100
|
0
|
|
563
|
my $callback = $options{callback} // sub { }; |
53
|
120
|
100
|
66
|
|
|
613
|
if (blessed $callback and $callback->isa('RDF::Trine::Model')) { |
54
|
5
|
|
|
|
|
71
|
require RDF::Trine::Statement; |
55
|
5
|
|
|
|
|
12
|
my $model = $callback; |
56
|
|
|
|
|
|
|
$callback = sub { |
57
|
12
|
|
|
12
|
|
19
|
eval { |
58
|
12
|
|
|
|
|
56
|
$model->add_statement( trine_statement(@_) ) |
59
|
|
|
|
|
|
|
}; |
60
|
12
|
100
|
|
|
|
22235
|
$self->error($@) if $@; |
61
|
5
|
|
|
|
|
27
|
}; |
62
|
|
|
|
|
|
|
} |
63
|
120
|
|
|
|
|
390
|
$self->{callback} = $callback; |
64
|
|
|
|
|
|
|
|
65
|
120
|
|
|
|
|
424
|
return $self; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub namespace_map { # sets the local namespace map |
69
|
102
|
|
|
102
|
0
|
322
|
my ($self, $map) = @_; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# TODO: copy on write because this is expensive! |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# copy default namespace map |
74
|
|
|
|
|
|
|
# TODO: respect '_' and default map! |
75
|
|
|
|
|
|
|
my $ns = ref $self->{ns} |
76
|
10
|
|
|
|
|
6071
|
? bless { %{$self->{ns}} }, 'RDF::NS' |
77
|
102
|
100
|
|
|
|
645
|
: RDF::NS->new($self->{ns}); |
78
|
|
|
|
|
|
|
|
79
|
102
|
100
|
|
|
|
2820681
|
if (ref $map) { |
80
|
4
|
100
|
|
|
|
19
|
if (ref $map eq 'HASH') { |
81
|
3
|
|
|
|
|
23
|
while (my ($prefix,$namespace) = each %$map) { |
82
|
3
|
50
|
|
|
|
9
|
$prefix = '' if $prefix eq '_'; |
83
|
3
|
100
|
|
|
|
27
|
if ($prefix !~ prefix) { |
|
|
100
|
|
|
|
|
|
84
|
1
|
|
|
|
|
5
|
$self->error("invalid prefix: $prefix"); |
85
|
|
|
|
|
|
|
} elsif ($namespace !~ IRIlike) { |
86
|
1
|
|
|
|
|
5
|
$self->error("invalid namespace: $namespace"); |
87
|
|
|
|
|
|
|
} else { |
88
|
1
|
|
|
|
|
6
|
$ns->{$prefix} = $namespace; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} else { |
92
|
1
|
|
|
|
|
6
|
$self->error("namespace map must be map or string"); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
99
|
|
|
|
|
484
|
$self->{ns} = $ns; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub decode { |
100
|
102
|
|
|
102
|
1
|
5435
|
my ($self, $map, %options) = @_; |
101
|
|
|
|
|
|
|
|
102
|
102
|
50
|
|
|
|
283
|
unless ($options{keep_bnode_map}) { |
103
|
102
|
|
|
|
|
247
|
$self->{bnode_map} = { }; |
104
|
|
|
|
|
|
|
} |
105
|
102
|
|
|
|
|
197
|
$self->{visited} = { }; |
106
|
|
|
|
|
|
|
|
107
|
102
|
|
|
|
|
472
|
$self->namespace_map( $map->{"_ns"} ); |
108
|
|
|
|
|
|
|
|
109
|
99
|
100
|
|
|
|
1278
|
if (exists $map->{_id}) { |
110
|
|
|
|
|
|
|
# predicate map |
111
|
|
|
|
|
|
|
|
112
|
30
|
|
|
|
|
85
|
my $id = $map->{_id}; |
113
|
30
|
100
|
|
|
|
136
|
return if $self->is_null($id,'_id'); |
114
|
|
|
|
|
|
|
|
115
|
27
|
100
|
|
|
|
130
|
my $subject = $id ne '' ? $self->expect_resource($id,'subject') : undef; |
116
|
23
|
100
|
66
|
|
|
108
|
if (defined $subject and $subject ne '') { |
|
|
50
|
|
|
|
|
|
117
|
22
|
|
|
|
|
74
|
$self->predicate_map( $subject, $map ); |
118
|
|
|
|
|
|
|
} elsif ($self->{strict}) { |
119
|
1
|
|
|
|
|
5
|
$self->error("invalid subject", $id); |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
} else { |
123
|
|
|
|
|
|
|
# 3.4.1 subject maps |
124
|
69
|
50
|
|
|
|
386
|
foreach my $key (grep { $_ ne '_' and $_ !~ /^_[^:]/ } keys %$map) { |
|
73
|
|
|
|
|
725
|
|
125
|
72
|
100
|
|
|
|
363
|
next if $self->is_null($key,'subject'); |
126
|
|
|
|
|
|
|
|
127
|
69
|
|
|
|
|
290
|
my $subject = $self->subject($key); |
128
|
68
|
100
|
|
|
|
179
|
if (!$subject) { |
129
|
7
|
|
|
|
|
29
|
$self->error("invalid subject", $key); |
130
|
0
|
|
|
|
|
0
|
next; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
61
|
|
|
|
|
113
|
my $predicates = $map->{$key}; |
134
|
61
|
100
|
100
|
|
|
202
|
if (exists $predicates->{_id} and ($self->resource($predicates->{_id}) // '') ne $subject) { |
|
|
|
66
|
|
|
|
|
135
|
3
|
|
|
|
|
16
|
$self->error("subject _id must be <$subject>"); |
136
|
|
|
|
|
|
|
} else { |
137
|
58
|
|
|
|
|
199
|
$self->predicate_map( $subject, $predicates ); |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub predicate_map { |
144
|
87
|
|
|
87
|
0
|
222
|
my ($self, $subject, $map) = @_; |
145
|
|
|
|
|
|
|
|
146
|
87
|
|
|
|
|
509
|
$self->{visited}{refaddr $map} = 1; |
147
|
|
|
|
|
|
|
|
148
|
87
|
|
|
|
|
345
|
for (keys %$map) { |
149
|
109
|
100
|
66
|
|
|
573
|
next if $_ eq '_id' or $_ eq '_ns'; |
150
|
|
|
|
|
|
|
|
151
|
85
|
50
|
|
|
|
129
|
my $predicate = do { |
152
|
85
|
100
|
|
|
|
452
|
if ($_ eq 'a') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
153
|
31
|
|
|
|
|
97
|
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; |
154
|
|
|
|
|
|
|
} elsif ( $_ =~ /^<(.+)>$/ ) { |
155
|
21
|
|
|
|
|
51
|
$self->iri($1); |
156
|
|
|
|
|
|
|
} elsif ( $_ =~ qName ) { |
157
|
27
|
|
|
|
|
99
|
$self->prefixed_name($1,$2); |
158
|
|
|
|
|
|
|
} elsif ( $_ =~ IRIlike ) { |
159
|
4
|
|
|
|
|
12
|
$self->iri($_); |
160
|
|
|
|
|
|
|
} else { |
161
|
|
|
|
|
|
|
$self->error("invalid predicate IRI $_") |
162
|
2
|
50
|
33
|
|
|
20
|
if $_ ne '' or $self->{strict}; |
163
|
0
|
|
|
|
|
0
|
next; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
} or next; |
166
|
|
|
|
|
|
|
|
167
|
81
|
|
|
|
|
168
|
my $value = $map->{$_}; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# encoded_object |
170
|
81
|
100
|
|
|
|
245
|
foreach my $o (ref $value eq 'ARRAY' ? @$value : $value) { |
171
|
87
|
100
|
|
|
|
211
|
if ($self->is_null($o,'object')) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
172
|
5
|
|
|
|
|
13
|
next; |
173
|
|
|
|
|
|
|
} elsif (!ref $o) { |
174
|
68
|
50
|
|
|
|
208
|
if (my $object = $self->object($o)) { |
175
|
67
|
|
|
|
|
237
|
$self->triple( $subject, $predicate, $object ); |
176
|
|
|
|
|
|
|
} |
177
|
67
|
|
|
|
|
18883
|
next; |
178
|
|
|
|
|
|
|
} elsif (ref $o eq 'HASH') { |
179
|
|
|
|
|
|
|
my $object = exists $o->{_id} |
180
|
10
|
100
|
50
|
|
|
54
|
? ($self->expect_resource($o->{_id},'object _id') // next) |
181
|
|
|
|
|
|
|
: $self->blank_identifier(); |
182
|
|
|
|
|
|
|
|
183
|
7
|
|
|
|
|
31
|
$self->triple( $subject, $predicate, [$object] ); |
184
|
|
|
|
|
|
|
|
185
|
7
|
50
|
33
|
|
|
122
|
unless( ref $object and $self->{visited}{refaddr $object} ) { |
186
|
7
|
|
|
|
|
78
|
$self->predicate_map( $object, $o ); |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
} else { |
189
|
2
|
|
|
|
|
8
|
$self->error('object must not be reference to '.ref $o); |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
sub is_null { |
196
|
194
|
|
|
194
|
0
|
437
|
my ($self, $value, $check) = @_; |
197
|
|
|
|
|
|
|
|
198
|
194
|
100
|
100
|
|
|
998
|
if ( !defined $value or (defined $self->{null} and $value eq $self->{null} ) ) { |
|
|
|
100
|
|
|
|
|
199
|
13
|
100
|
66
|
|
|
63
|
if ($check and $self->{strict}) { |
200
|
4
|
|
|
|
|
22
|
$self->error("$check must not be null") |
201
|
|
|
|
|
|
|
} |
202
|
9
|
|
|
|
|
34
|
1; |
203
|
|
|
|
|
|
|
} else { |
204
|
181
|
|
|
|
|
622
|
0; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub expect_resource { |
209
|
31
|
|
|
31
|
0
|
88
|
my ($self, $r, $expect) = @_; |
210
|
31
|
100
|
|
|
|
249
|
if (my $resource = $self->resource($r)) { |
211
|
24
|
|
|
|
|
64
|
return $resource; |
212
|
|
|
|
|
|
|
} else { |
213
|
5
|
50
|
|
|
|
19
|
if (!$self->is_null($r, $expect)) { |
214
|
5
|
100
|
|
|
|
30
|
$expect .= ": " . (ref $r ? reftype $r : $r); |
215
|
5
|
|
|
|
|
21
|
$self->error("invalid $expect"); |
216
|
|
|
|
|
|
|
} |
217
|
0
|
|
|
|
|
0
|
return; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub resource { |
222
|
72
|
|
|
72
|
0
|
155
|
my ($self, $r) = @_; |
223
|
|
|
|
|
|
|
|
224
|
72
|
100
|
|
|
|
166
|
return unless defined $r; |
225
|
|
|
|
|
|
|
|
226
|
71
|
100
|
|
|
|
456
|
if ( $r =~ explicitIRIlike ) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
227
|
21
|
|
|
|
|
56
|
$self->iri($1); |
228
|
|
|
|
|
|
|
} elsif ( $r =~ blankNode ) { |
229
|
2
|
|
|
|
|
8
|
$self->blank_identifier($1); |
230
|
|
|
|
|
|
|
} elsif ( $r =~ qName ) { |
231
|
2
|
|
|
|
|
11
|
$self->prefixed_name($1,$2); |
232
|
|
|
|
|
|
|
} elsif ( $r =~ IRIlike ) { |
233
|
38
|
|
|
|
|
116
|
$self->iri($r); |
234
|
|
|
|
|
|
|
} else { |
235
|
|
|
|
|
|
|
undef |
236
|
8
|
|
|
|
|
24
|
} |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub subject { # plain IRI, qName, or blank node |
240
|
69
|
|
|
69
|
1
|
160
|
my ($self, $s) = @_; |
241
|
|
|
|
|
|
|
|
242
|
69
|
50
|
|
|
|
169
|
return unless defined $s; |
243
|
|
|
|
|
|
|
|
244
|
69
|
100
|
|
|
|
497
|
if ( $s =~ IRIlike ) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
245
|
57
|
|
|
|
|
281
|
$self->iri($s); |
246
|
|
|
|
|
|
|
} elsif ( $s =~ qName ) { |
247
|
2
|
|
|
|
|
11
|
$self->prefixed_name($1,$2); |
248
|
|
|
|
|
|
|
} elsif ( $s =~ blankNode ) { |
249
|
3
|
|
|
|
|
12
|
$self->blank_identifier($1); |
250
|
|
|
|
|
|
|
} else { |
251
|
|
|
|
|
|
|
undef |
252
|
7
|
|
|
|
|
15
|
} |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub object { |
256
|
133
|
|
|
133
|
1
|
272
|
my ($self, $o) = @_; |
257
|
|
|
|
|
|
|
|
258
|
133
|
50
|
|
|
|
1099
|
if (!defined $o) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
259
|
0
|
|
|
|
|
0
|
undef; |
260
|
|
|
|
|
|
|
} elsif ( $o =~ explicitIRIlike ) { |
261
|
7
|
|
|
|
|
23
|
[$self->iri($1)]; |
262
|
|
|
|
|
|
|
} elsif ( $o =~ blankNode ) { |
263
|
3
|
|
|
|
|
10
|
[$self->blank_identifier($1)]; |
264
|
|
|
|
|
|
|
} elsif ( $o =~ qName ) { |
265
|
21
|
|
|
|
|
62
|
[$self->prefixed_name($1,$2)]; |
266
|
|
|
|
|
|
|
} elsif ( $o =~ languageString ) { |
267
|
22
|
|
|
|
|
96
|
[$1, lc($2)]; |
268
|
|
|
|
|
|
|
} elsif ( $o =~ /^(.*)[@]$/ ) { |
269
|
23
|
|
|
|
|
108
|
[$1, undef]; |
270
|
|
|
|
|
|
|
} elsif ( $o =~ datatypeString ) { |
271
|
16
|
100
|
|
|
|
62
|
if ($6) { |
272
|
6
|
|
50
|
|
|
19
|
my $datatype = $self->iri($6) // return; |
273
|
6
|
100
|
|
|
|
18
|
if ($datatype eq xsd_string) { |
274
|
2
|
|
|
|
|
11
|
[$1,undef]; |
275
|
|
|
|
|
|
|
} else { |
276
|
4
|
|
|
|
|
21
|
[$1,undef,$datatype]; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
} else { |
279
|
10
|
|
50
|
|
|
35
|
my $datatype = $self->prefixed_name($4,$5) // return; |
280
|
9
|
100
|
|
|
|
31
|
if ($datatype eq xsd_string) { |
281
|
3
|
|
|
|
|
13
|
[$1,undef]; |
282
|
|
|
|
|
|
|
} else { |
283
|
6
|
|
|
|
|
36
|
[$1,undef,$datatype]; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
} elsif ( $o =~ IRIlike ) { |
287
|
29
|
|
|
|
|
72
|
[$self->iri($o)]; |
288
|
|
|
|
|
|
|
} else { |
289
|
12
|
|
|
|
|
48
|
[$o, undef]; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub plain_literal { |
294
|
6
|
|
|
6
|
0
|
2073
|
my ($self, $object) = @_; |
295
|
6
|
|
|
|
|
12
|
my $obj = $self->object($object); |
296
|
6
|
100
|
|
|
|
18
|
return if @$obj == 1; # resource or blank |
297
|
4
|
|
|
|
|
12
|
return $obj->[0]; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
sub iri { |
301
|
246
|
|
|
246
|
0
|
596
|
my ($self, $iri) = @_; |
302
|
|
|
|
|
|
|
# TODO: check full RFC form of IRIs |
303
|
246
|
100
|
|
|
|
747
|
if ( $iri !~ IRIlike ) { |
304
|
1
|
|
|
|
|
5
|
return $self->error("invalid IRI $iri"); |
305
|
|
|
|
|
|
|
} else { |
306
|
245
|
|
|
|
|
794
|
return $iri; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub prefixed_name { |
311
|
68
|
|
|
68
|
0
|
339
|
my ($self, $prefix, $name) = @_; |
312
|
68
|
50
|
50
|
|
|
336
|
my $base = $self->{ns}{$prefix // ''} |
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
313
|
|
|
|
|
|
|
// return $self->error( |
314
|
|
|
|
|
|
|
$prefix // '' ne '' |
315
|
|
|
|
|
|
|
? "unknown prefix: $prefix" : "not an URI: $name"); |
316
|
63
|
|
|
|
|
222
|
$self->iri($base.$name); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub triple { |
320
|
74
|
|
|
74
|
0
|
153
|
my $self = shift; |
321
|
74
|
100
|
|
|
|
174
|
my $subject = ref $_[0] ? '_:'.${$_[0]} : $_[0]; |
|
6
|
|
|
|
|
17
|
|
322
|
74
|
|
|
|
|
120
|
my $predicate = $_[1]; |
323
|
74
|
|
|
|
|
99
|
my @object = @{$_[2]}; |
|
74
|
|
|
|
|
244
|
|
324
|
74
|
100
|
|
|
|
181
|
$object[0] = '_:'.${$object[0]} if ref $object[0]; |
|
10
|
|
|
|
|
36
|
|
325
|
74
|
|
|
|
|
320
|
$self->{callback}->($subject, $predicate, @object); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub error { |
329
|
34
|
|
|
34
|
0
|
124
|
my ($self, $message, $value, $context) = @_; |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# TODO: include $context (bless $message, 'RDF::aREF::Error') |
332
|
|
|
|
|
|
|
|
333
|
34
|
100
|
|
|
|
81
|
if (defined $value) { |
334
|
8
|
50
|
|
|
|
31
|
$message .= ': ' . (ref $value ? reftype $value : $value); |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
34
|
50
|
|
|
|
191
|
if (!$self->{complain}) { |
|
|
100
|
|
|
|
|
|
338
|
0
|
|
|
|
|
0
|
return; |
339
|
|
|
|
|
|
|
} elsif ($self->{complain} == 1) { |
340
|
1
|
|
|
|
|
43
|
carp $message; |
341
|
|
|
|
|
|
|
} else { |
342
|
33
|
|
|
|
|
5217
|
croak $message; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub bnode_count { |
347
|
2
|
100
|
|
2
|
1
|
824
|
$_[0]->{bnode_count} = $_[1] if @_ > 1; |
348
|
2
|
|
|
|
|
8
|
$_[0]->{bnode_count}; |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# TODO: test this |
352
|
|
|
|
|
|
|
sub blank_identifier { |
353
|
13
|
|
|
13
|
0
|
38
|
my ($self, $id) = @_; |
354
|
|
|
|
|
|
|
|
355
|
13
|
|
|
|
|
37
|
my $bnode; |
356
|
13
|
100
|
|
|
|
71
|
if ( defined $id ) { |
357
|
8
|
|
66
|
|
|
53
|
$bnode = ($self->{bnode_map}{$id} //= $self->{bnode_prefix} . ++$self->{bnode_count}); |
358
|
|
|
|
|
|
|
} else { |
359
|
5
|
|
|
|
|
17
|
$bnode = $self->{bnode_prefix} . ++$self->{bnode_count}; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
13
|
|
|
|
|
111
|
return \$bnode; |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub clean_bnodes { |
366
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
367
|
0
|
|
|
|
|
0
|
$self->{bnode_count} = 0; |
368
|
0
|
|
|
|
|
0
|
$self->{bnode_map} = {}; |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# TODO: test this |
372
|
|
|
|
|
|
|
sub trine_statement { |
373
|
|
|
|
|
|
|
RDF::Trine::Statement->new( |
374
|
|
|
|
|
|
|
# subject |
375
|
|
|
|
|
|
|
(substr($_[0],0,2) eq '_:' ? RDF::Trine::Node::Blank->new(substr $_[0], 2) |
376
|
|
|
|
|
|
|
: RDF::Trine::Node::Resource->new($_[0])), |
377
|
|
|
|
|
|
|
# predicate |
378
|
|
|
|
|
|
|
RDF::Trine::Node::Resource->new($_[1]), |
379
|
|
|
|
|
|
|
# object |
380
|
22
|
100
|
|
22
|
0
|
358
|
do { |
381
|
22
|
100
|
|
|
|
978
|
if (@_ == 3) { |
382
|
15
|
100
|
|
|
|
45
|
if (substr($_[2],0,2) eq '_:') { |
383
|
5
|
|
|
|
|
26
|
RDF::Trine::Node::Blank->new(substr $_[2], 2); |
384
|
|
|
|
|
|
|
} else { |
385
|
10
|
|
|
|
|
25
|
RDF::Trine::Node::Resource->new($_[2]); |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
} else { |
388
|
7
|
|
|
|
|
51
|
RDF::Trine::Node::Literal->new($_[2],$_[3],$_[4]); |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
); |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
1; |
396
|
|
|
|
|
|
|
__END__ |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=head1 NAME |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
RDF::aREF::Decoder - decode another RDF Encoding Form (to RDF triples) |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=head1 SYNOPSIS |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
use RDF::aREF::Decoder; |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
RDF::aREF::Decoder->new( %options )->decode( $aref ); |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head1 DESCRIPTION |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
This module implements a decoder from another RDF Encoding Form (aREF), given |
411
|
|
|
|
|
|
|
as in form of Perl arrays, hashes, and Unicode strings, to RDF triples. |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=head1 OPTIONS |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=head2 ns |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
A default namespace map, given either as hash reference or as version string of |
418
|
|
|
|
|
|
|
module L<RDF::NS>. Set to the most recent version of RDF::NS by default, but relying |
419
|
|
|
|
|
|
|
on a default value is not recommended! |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=head2 callback |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
A code reference that is called for each triple with a list of three to five |
424
|
|
|
|
|
|
|
elements: |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=over |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=item subject |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
The subject IRI or subject blank node as string. Blank nodes always start with |
431
|
|
|
|
|
|
|
C<_:>. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=item predicate |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
The predicate IRI. |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=item object |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
The object IRI or object blank node or literal object as string. Blank nodes |
440
|
|
|
|
|
|
|
always start with C<_:> and literal objects can be detected by existence of the |
441
|
|
|
|
|
|
|
(possibly empty) language or datatype element. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=item language |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
The language tag (possible the empty string) for literal objects. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=item datatype |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
The object's datatype if object is a literal and datatype is not |
450
|
|
|
|
|
|
|
C<http://www.w3.org/2001/XMLSchema#string>. |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
=back |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
For convenience an instance of L<RDF::Trine::Model> can also be used as |
455
|
|
|
|
|
|
|
callback. |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=head2 complain |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
What to do on errors. Set to 1 be default (warn). Set to 0 to ignore. Other |
460
|
|
|
|
|
|
|
values will die on errors. |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
=head2 strict |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Enables errors on undefined subjects, predicates, and objects. By default |
465
|
|
|
|
|
|
|
the Perl value C<undef> in any part of an encoded RDF triple will silently |
466
|
|
|
|
|
|
|
ignore the triple, so aREF structures can easily be used as templates with |
467
|
|
|
|
|
|
|
optional values. |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=head2 null |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
A null object that is treated equivalent to C<undef> if found as object. For |
472
|
|
|
|
|
|
|
instance setting this to the empty string will ignore all triples with the |
473
|
|
|
|
|
|
|
empty string as literal value. |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
=head2 bnode_prefix |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
A prefix for blank node identifiers. Defaults to "b", so blank node identifiers |
478
|
|
|
|
|
|
|
will be "b1", "b2", "b3" etc. |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=head2 bnode_count |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
An integer to start creating blank node identifiers with. The default value "0" |
483
|
|
|
|
|
|
|
results in blank node identifiers starting from "b1". This option can be useful |
484
|
|
|
|
|
|
|
to avoid collision of blank node identifiers when merging multiple aREF |
485
|
|
|
|
|
|
|
instances. The current counter value is accessible as accessor. |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
=head1 METHODS |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
=head2 decode( $aref [, keep_bnode_map => 1 ] ) |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
Encode RDF data given in aREF. Resets all blank node identifier mappings unless |
492
|
|
|
|
|
|
|
option c<keep_bnode_map> is set. |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=head2 clean_bnodes |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Delete blank node identifier mapping and reset bnode_count. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=head1 EXPORTABLE CONSTANTS |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
On request this module exports the following regular expressions, as defined in the |
501
|
|
|
|
|
|
|
L<aREF specification|http://gbv.github.io/aREF/aREF.html>: |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=over |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
=item qName |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
=item blankNode |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
=item IRIlike |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=item languageString |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=item languageTag |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=item datatypeString |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
=back |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=head1 SEE ALSO |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
L<RDF::aREF::Encoder> |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=cut |