File Coverage

blib/lib/WWW/ASN.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package WWW::ASN;
2 1     1   21847 use strict;
  1         3  
  1         95  
3 1     1   4 use warnings;
  1         2  
  1         24  
4 1     1   1050 use Moo;
  1         17198  
  1         7  
5             extends 'WWW::ASN::Downloader';
6              
7 1     1   2575 use XML::Twig;
  0            
  0            
8              
9             use WWW::ASN::Jurisdiction;
10             use WWW::ASN::Subject;
11              
12              
13             =head1 NAME
14              
15             WWW::ASN - Retrieve learning objectives from Achievement Standards Network
16              
17             =cut
18              
19             our $VERSION = '0.01';
20              
21             has jurisdictions_cache => (
22             is => 'ro',
23             );
24              
25             has subjects_cache => (
26             is => 'ro',
27             );
28              
29             =head1 SYNOPSIS
30              
31             Without using caches:
32              
33             use WWW::ASN;
34              
35             my $asn = WWW::ASN->new;
36             for my $jurisdiction (@{ $asn->jurisdictions }) {
37             # $jurisdiction is a WWW::ASN::Jurisdiction object
38              
39             if ($jurisdictions->name =~ /Common Core/i) {
40             for my $document (@{ $jurisdictions->documents({ status => 'published' }) }) {
41             # $document is a WWW::ASN::Document object
42              
43             for my $standard (@{ $document->standards }) {
44             # $standard is a WWW::ASN::Standard document
45             print $standard->identifier, ": ", $standard->text;
46             ...
47             for my $sub_standard (@{ $standard->child_standards }) {
48             ...
49             }
50             }
51             }
52             }
53             }
54              
55             Another example, With cache files (recommended, if possible):
56              
57             use WWW::ASN;
58             use URI::Escape qw(uri_escape);
59              
60             my $asn = WWW::ASN->new({
61             jurisdictions_cache => 'jurisdictions.xml',
62             subjects_cache => 'subjects.xml',
63             });
64             for my $jurisdiction (@{ $asn->jurisdictions }) {
65             my $docs_cache = 'doclist_' . $jurisdiction->abbreviation . '.xml';
66             for my $doc (@{ $jurisdictions->documents({ cache_file => $docs_cache }) }) {
67             # Set these cache values before calling standards()
68             $doc->details_cache_file(
69             "doc_" . $jurisdiction->abbreviation . '_details_' . uri_escape($doc->id)
70             );
71             $doc->manifest_cache_file(
72             "doc_" . $jurisdiction->abbreviation . '_manifest_' . uri_escape($doc->id);
73             );
74             for my $standard (@{ $document->standards }) {
75             # $standard is a WWW::ASN::Standard document
76             ...
77             for my $sub_standard (@{ $standard->child_standards }) {
78             ...
79             }
80             }
81             }
82             }
83              
84             =head1 DESCRIPTION
85              
86             This module allows you to retrieve standards documents from
87             the Achievement Standards Network (L).
88              
89             As illustrated in the L, you will typically first
90             retrieve a L such as a state,
91             or other organization that creates L.
92             From this jurisdiction you can then retrieve specific documents.
93              
94             B Because this is such a niche module and there aren't many expected
95             users, some of the documentation may take for granted your familiarity
96             with the Achievement Standards Network.
97             If you have difficulties using this module, please feel free to
98             contact the author with any questions
99              
100             =head2 Cache files
101              
102             Many of the methods in these modules allow for the use
103             of cache files. The main purpose of these options is to allow
104             you to be a good citizen and avoid unnecessary hits to the
105             ASN website during your development and testing.
106              
107             Using them is very simple: Just provide a file name. That's it!
108              
109             When a filename is provided it will be used
110             instead of downloading the data again - unless the file doesn't
111             exist, in which case the data will be downloaded and saved
112             to the file.
113              
114             =head1 ATTRIBUTES
115              
116             =head2 jurisdictions_cache
117              
118             Optional. The name of a file containing the XML data from
119             http://asn.jesandco.org/api/1/jurisdictions
120              
121             If the file does not exist, it will be created.
122              
123             Leave this option undefined to force retrieval
124             each time L is called.
125              
126             =head2 subjects_cache
127              
128             Optional. The name of a file containing the XML data from
129             http://asn.jesandco.org/api/1/subjects
130              
131             If the file does not exist, it will be created.
132              
133             Leave this option undefined to force retrieval
134             each time L is called.
135              
136             =head1 METHODS
137              
138             In addition to get/set methods for each of the attributes above,
139             the following methods can be called:
140              
141             =head2 jurisdictions
142              
143             Returns an array reference of L objects.
144              
145             =cut
146              
147             sub jurisdictions {
148             my $self = shift;
149              
150             my $jurisdictions_xml = $self->_read_or_download(
151             $self->jurisdictions_cache,
152             'http://asn.jesandco.org/api/1/jurisdictions',
153             );
154              
155             my @rv = ();
156             my $handle_jurisdiction = sub {
157             my ($twig, $jur) = @_;
158              
159             my %jur_params = ();
160             for my $info ($jur->children) {
161             my $tag = $info->tag;
162              
163             my $val = $info->text;
164              
165             # tags should be organizationName, organizationAlias, ...
166             # with 'DocumentCount' being the exception
167             $tag =~ s/^organization//;
168             $tag = lc $tag;
169              
170             if ($tag eq 'name') {
171             $jur_params{name} = $val;
172             } elsif ($tag eq 'alias') {
173             $jur_params{id} = $val;
174             } elsif ($tag eq 'jurisdiction') {
175             $jur_params{abbreviation} = $val;
176             } elsif ($tag eq 'class') {
177             $jur_params{type} = $val;
178             } elsif ($tag eq 'documentcount') {
179             $jur_params{document_count} = $val;
180             } else {
181             warn "Unknown tag in Jurisdiction: " . $info->tag;
182             }
183             }
184             push @rv, WWW::ASN::Jurisdiction->new(%jur_params);
185             };
186              
187             my $twig = XML::Twig->new(
188             twig_handlers => {
189             '/asnJurisdictions/Jurisdiction' => $handle_jurisdiction,
190             },
191             );
192             $twig->parse($jurisdictions_xml);
193              
194             return \@rv;
195             }
196              
197             =head2 subjects
198              
199             Returns an array reference of L objects.
200              
201             =cut
202              
203             sub subjects {
204             my $self = shift;
205              
206             my $subjects_xml = $self->_read_or_download(
207             $self->subjects_cache,
208             'http://asn.jesandco.org/api/1/subjects',
209             );
210              
211             my @rv = ();
212             my $handle_subject = sub {
213             my ($twig, $subject) = @_;
214              
215             push @rv, WWW::ASN::Subject->new(
216             id => $subject->first_child('SubjectIdentifier')->text,
217             name => $subject->first_child('Subject')->text,
218             document_count => $subject->first_child('DocumentCount')->text,
219             );
220             };
221              
222             my $twig = XML::Twig->new(
223             twig_handlers => {
224             '/asnSubjects/Subject' => $handle_subject,
225             },
226             );
227             $twig->parse($subjects_xml);
228              
229             return \@rv;
230             }
231              
232             =head1 TODO
233              
234             =over 4
235              
236             =item *
237              
238             Currently you need to start with a jurisdiction (either from calling C
239             on a C object, or by creating one with an C attribute (and
240             optionally other attributes), then looping its documents, then fetching their standards.
241              
242             Ideally the interface should give you more direct routes to get to the data you're interested in.
243              
244             =cut
245              
246             =item *
247              
248             When a L creates a L object, it has to fetch two
249             documents, the "details" xml and the "manifest" json.
250              
251             Ideally this would get everything from the "details" document. We use both though, since it's
252             simpler and took less time to parse the manifest than the xml.
253              
254             =item *
255              
256             Investigate the feasibility of interfacing with the SPARQL endpoint to allow
257             for more powerful queries.
258              
259             e.g. get a list of recently updated documents.
260              
261             =back
262              
263             =head1 AUTHOR
264              
265             Mark A. Stratman, C<< >>
266              
267             =head1 SEE ALSO
268              
269             L
270              
271             L
272              
273             L
274              
275             L
276              
277             =head1 ACKNOWLEDGEMENTS
278              
279             This library retrieves and manipulates data from the Achievement Standards Network.
280             L
281              
282              
283             =head1 LICENSE AND COPYRIGHT
284              
285             Copyright 2012 Mark A. Stratman.
286              
287             This program is free software; you can redistribute it and/or modify it
288             under the terms of either: the GNU General Public License as published
289             by the Free Software Foundation; or the Artistic License.
290              
291             See http://dev.perl.org/licenses/ for more information.
292              
293              
294             =cut
295              
296             1; # End of WWW::ASN