File Coverage

lib/FAIR/Base.pm
Criterion Covered Total %
statement 103 103 100.0
branch 19 24 79.1
condition 4 6 66.6
subroutine 13 13 100.0
pod 0 2 0.0
total 139 148 93.9


line stmt bran cond sub pod time code
1             package FAIR::Base;
2             $FAIR::Base::VERSION = '0.230';
3              
4              
5             # ABSTRACT: libraries for creating and parsing FAIR Data Profiles (see http://datafairport.org for more details)
6              
7 6     6   2711 use RDF::NS '20131205';
  6         53392  
  6         215  
8 6     6   58 use strict;
  6         15  
  6         151  
9 6     6   31 use RDF::Trine::Store::Memory;
  6         12  
  6         205  
10 6     6   31 use RDF::Trine::Model;
  6         11  
  6         171  
11 6     6   31 use RDF::Trine::Namespace;
  6         12  
  6         64  
12 6     6   220 use RDF::Trine::Statement;
  6         10  
  6         164  
13 6     6   31 use RDF::Trine::Node::Resource;
  6         8  
  6         358  
14 6     6   31 use RDF::Trine::Node::Literal;
  6         13  
  6         318  
15              
16              
17 6     6   33 use Exporter qw(import);
  6         10  
  6         406  
18             our @ISA = qw(Exporter);
19             our @EXPORT = qw(statement);
20              
21 6     6   2701 use FAIR::NAMESPACES;
  6         14  
  6         8759  
22              
23             our %predicate_namespaces = qw{
24             type RDF
25             title DC
26             description DC
27             issued DC
28             modified DC
29             identifier DC
30             keyword DC
31             language DC
32             contactPoint DC
33             temporal DC
34             spatial DC
35             accrualPeriodicity DC
36             landingPage DCAT
37             license DC
38             rights DC
39             accessURL DCAT
40             downloadURL DCAT
41             mediaType DCAT
42             format DC
43             byteSize DCAT
44             homepage FOAF
45             publisher DC
46             theme DCAT
47             inScheme SKOS
48             themeTaxonomy DCAT
49             dataset DCAT
50             record DCAT
51             distribution DCAT
52             primaryTopic FOAF
53             provenance DC
54             ProvenanceStatement DC
55            
56             label RDFS
57             organization DC
58             hasClass FAIR
59             hasProperty FAIR
60             onClassType FAIR
61             onPropertyType FAIR
62             allowedValues FAIR
63             maxCount FAIR
64             minCount FAIR
65             FAIRClass FAIR
66             FAIRProperty FAIR
67             FAIRProfile FAIR
68            
69             schemardfs_URL FAIR
70            
71             };
72              
73              
74             sub _toTriples {
75 20     20   37 my ($self, $model) = @_;
76 20 100       56 unless ($model){ # this is a recursive sub, so sometimes the preexisting model is passed in to be filled
77 5         18 my $store = RDF::Trine::Store::Memory->new();
78 5         92 $model = RDF::Trine::Model->new($store);
79             }
80 20         61 my %namespaces;
81 20         59 my $dct = RDF::Trine::Namespace->new( DC); # from shared exported constants in NAMESPACES.pm
82 20         124 $namespaces{DC} = $dct;
83            
84 20         49 my $dcat = RDF::Trine::Namespace->new( DCAT);
85 20         75 $namespaces{DCAT} = $dcat;
86            
87 20         49 my $skos = RDF::Trine::Namespace->new( SKOS);
88 20         69 $namespaces{SKOS} = $skos;
89              
90 20         47 my $foaf = RDF::Trine::Namespace->new( FOAF);
91 20         75 $namespaces{FOAF} = $foaf;
92              
93 20         43 my $rdfs = RDF::Trine::Namespace->new( RDFS);
94 20         70 $namespaces{RDFS} = $rdfs;
95              
96 20         46 my $rdf = RDF::Trine::Namespace->new( RDF);
97 20         77 $namespaces{RDF} = $rdf;
98              
99 20         35 my $fair = RDF::Trine::Namespace->new( FAIR);
100 20         84 $namespaces{FAIR} = $fair;
101              
102              
103             # now go through all of the properties of that subject to begin constructing the triples
104 20         22 my %attributes;
105 20         85 map {$attributes{$_} = 1} $self->meta->get_attribute_list;
  155         742  
106 20         571 my $sub = $self->URI; # the subject of the triples
107 20         41 delete $attributes{'URI'}; # this attribute we have taken care of
108            
109 20         387 my $types = $self->type;
110 20         48 foreach my $type(@$types){
111 25         10656 my $stm = statement($sub, RDF."type", $type);
112 25         90 $model->add_statement($stm);
113             }
114 20         13001 delete $attributes{'type'}; # now we've taken care of that one!
115              
116            
117             # now process the rest - serialize the property if it is marked as "serializable";
118 20         63 foreach my $attributename(keys %attributes){
119 115         40806 my $attribute = $self->meta->get_attribute($attributename);
120 115 50       2332 next unless $attribute->does('Serializable'); # if this isn't a serializable property, skip it
121 115         21014 my $predicate = $attribute->name; # the FAIR Moose object predicate names are identical to the OWL/Schema predicate names,
122 115         296 my $reader = $attribute->get_read_method; # in case there is a specific reader subroutine associated with the property
123 115         2980 my $values = $self->$reader; # call the subroutine. All return a list-ref; sometimes its a list of DCAT objects, sometimes a listref of strings
124            
125 115 100       512 unless (ref($values) ~~ /ARRAY/){ # some properties return listrefs, others return just a string or an object
126 110         162 $values = [$values] # so force it to be a listref before we iterate over the return value
127             }
128 115         190 foreach my $object(@$values){
129             #print STDERR $object, "\n";
130 120 100       218 next unless ($object); # might be undef
131 105 100 66     473 if ((ref($object) ~~ /FAIR/) && $object->can('_toTriples')) { # is it a FAIR object? if so, unpack it
132 20         426 my $toConnect = $object->URI; # get that objects URI
133 20         54 my $namespace = $namespaces{$predicate_namespaces{$predicate}}; # look up the namespace of that predicate
134 20 50       69 die "no namespace found for $predicate\n" unless $namespace;
135 20         178 my $stm = statement($sub, $namespace.$predicate, $toConnect); # and create the triple joining that object to the current model
136 20         73 $model->add_statement($stm);
137 20 100       12835 next if ($object->isa('FAIR::Profile')); # if the sub-object refers back to the main profile object, then skip at this point to prevent infinite loops
138 15         57 $object->_toTriples($model); # recursive call... unpack that FAIR object to its triples
139             } else { # if it isn't a FAIR object, then it's just a listref of strings
140 85         162 my $namespace = $namespaces{$predicate_namespaces{$predicate}};
141 85         330 my $stm = statement($sub, $namespace.$predicate, $object);
142 85         265 $model->add_statement($stm);
143             }
144             }
145             # next;
146             #} else {
147             # # print STDERR $key, "\n";
148             # my $namespace = $namespaces{$predicate_namespaces{$key}};
149             # my $value = $self->$key;
150             # next unless defined $value;
151             # my $stm = statement($sub, $namespace.$key, $value);
152             # $model->add_statement($stm);
153             #}
154             }
155 20         9055 return $model;
156             }
157              
158             sub toTriples {
159 5     5 0 13 my ($self) = @_;
160 5         22 my $model = $self->_toTriples;
161 5         21 my $iter = $model->get_statements();
162 5         1871 my @statements;
163 5         24 while (my $st = $iter->next) {
164 130         8097 push @statements, $st;
165             }
166 5         251 return @statements;
167             }
168              
169              
170             sub statement {
171 130     130 0 583 my ($s, $p, $o) = @_;
172 130 50       260 unless (ref($s) =~ /Trine/){
173 130         238 $s =~ s/[\<\>]//g;
174 130         436 $s = RDF::Trine::Node::Resource->new($s);
175             }
176 130 50       1466 unless (ref($p) =~ /Trine/){
177 130         170 $p =~ s/[\<\>]//g;
178 130         225 $p = RDF::Trine::Node::Resource->new($p);
179             }
180 130 50       1077 unless (ref($o) =~ /Trine/){
181 130 100 66     651 if (($o =~ m'^http://') || ($o =~ m'^https://')){
    100          
182 60         87 $o =~ s/[\<\>]//g;
183 60         109 $o = RDF::Trine::Node::Resource->new($o);
184             } elsif ($o =~ /\D/) {
185 55         168 $o = RDF::Trine::Node::Literal->new($o);
186             } else {
187 15         42 $o = RDF::Trine::Node::Literal->new($o);
188             }
189             }
190 130         1864 my $statement = RDF::Trine::Statement->new($s, $p, $o);
191 130         1619 return $statement;
192             }
193              
194              
195              
196              
197              
198              
199              
200              
201              
202              
203              
204              
205             1;
206              
207             __END__
208              
209             =pod
210              
211             =encoding UTF-8
212              
213             =head1 NAME
214              
215             FAIR::Base - libraries for creating and parsing FAIR Data Profiles (see http://datafairport.org for more details)
216              
217             =head1 VERSION
218              
219             version 0.230
220              
221             =head1 FAIR Base - the root of the FAIR modules
222              
223             The FAIR modules come from the Data FAIRport project (http://datafairport.org).
224              
225             There are three main sections to this code: FAIR::Profiles, FAIR Accessors, and FAIR Projectors. (Projectors haven't been invented yet)
226              
227             =head1 AUTHOR
228              
229             Mark Denis Wilkinson (markw [at] illuminae [dot] com)
230              
231             =head1 COPYRIGHT AND LICENSE
232              
233             This software is Copyright (c) 2015 by Mark Denis Wilkinson.
234              
235             This is free software, licensed under:
236              
237             The Apache License, Version 2.0, January 2004
238              
239             =cut