File Coverage

blib/lib/XML/NewsML_G2/Writer/News_Item.pm
Criterion Covered Total %
statement 233 256 91.0
branch 64 86 74.4
condition 6 15 40.0
subroutine 24 24 100.0
pod n/a
total 327 381 85.8


line stmt bran cond sub pod time code
1             package XML::NewsML_G2::Writer::News_Item;
2              
3 18     18   138 use Scalar::Util qw(looks_like_number);
  18         43  
  18         1148  
4 18     18   118 use Moose;
  18         43  
  18         124  
5 18     18   117364 use namespace::autoclean;
  18         48  
  18         155  
6              
7             extends 'XML::NewsML_G2::Writer::Substancial_Item';
8              
9             has 'news_item',
10             isa => 'XML::NewsML_G2::News_Item',
11             is => 'ro',
12             required => 1;
13              
14             sub _build__root_item {
15 64     64   142 my $self = shift;
16 64         2054 return $self->news_item;
17             }
18              
19             sub _create_rights_info {
20 57     57   180 my ( $self, $root ) = @_;
21 57 100       1986 return unless $self->news_item->copyright_holder;
22              
23 48         208 my $ri = $self->create_element('rightsInfo');
24              
25 48         1464 $ri->appendChild(
26             my $crh = $self->create_element(
27             'copyrightHolder',
28             _name_text => $self->news_item->copyright_holder
29             )
30             );
31 48 50       1143 $crh->setAttribute( 'uri', $self->news_item->copyright_holder->uri )
32             if $self->news_item->copyright_holder->uri;
33 48 50       1773 if ( my $qcode = $self->news_item->copyright_holder->qcode ) {
34 48         1259 $self->scheme_manager->add_qcode_or_literal( $crh,
35             'copyright_holder', $qcode );
36             }
37              
38 48         367 $self->_create_copyright_holder_remoteinfo($crh);
39              
40 48         1942 my $notice = $self->news_item->copyright_holder->notice;
41 48 50       295 $ri->appendChild(
42             $self->create_element( 'copyrightNotice', _text => $notice ) )
43             if $notice;
44 48 100       148 $ri->appendChild(
45             $self->create_element(
46             'usageTerms', _text => $self->news_item->usage_terms
47             )
48             ) if $self->news_item->usage_terms;
49              
50 48         149 $root->appendChild($ri);
51 48         1041 return;
52             }
53              
54             sub _create_hierarchy {
55              
56             # my ($self, $node, $schema) = @_;
57             # code moved to Writer_2_9
58 188     188   387 return;
59             }
60              
61             sub _create_icon {
62              
63             #overwrite me
64 55     55   118 return;
65             }
66              
67             sub _create_subjects_desk {
68 64     64   144 my $self = shift;
69 64         131 my @res;
70              
71 64 100       1834 push @res, $self->doc->createComment('desks')
72             if $self->news_item->has_desks;
73 64         175 foreach ( sort { $a->qcode cmp $b->qcode } @{ $self->news_item->desks } )
  0         0  
  64         1843  
74             {
75 53         222 push @res,
76             my $s = $self->create_element(
77             'subject',
78             type => 'cpnat:abstract',
79             _name_text => $_
80             );
81 53         2505 $self->scheme_manager->add_qcode_or_literal( $s, 'desk', $_->qcode );
82             }
83 64         206 return @res;
84             }
85              
86             sub _create_subjects_storytypes {
87 64     64   149 my $self = shift;
88 64         122 my @res;
89              
90             push @res, $self->doc->createComment('storytypes')
91 64 50       125 if ( @{ $self->news_item->storytypes } );
  64         2082  
92              
93 64         173 foreach ( sort { $a->qcode cmp $b->qcode }
  0         0  
94 64         1815 @{ $self->news_item->storytypes } ) {
95 0         0 push @res,
96             my $s = $self->create_element(
97             'subject',
98             type => 'cpnat:abstract',
99             _name_text => $_
100             );
101 0         0 $self->scheme_manager->add_qcode_or_literal( $s, 'storytype',
102             $_->qcode );
103             }
104 64         210 return @res;
105             }
106              
107             sub _sort_subjects_locations {
108 138 50 33 138   676 if ( looks_like_number($a) && looks_like_number($b) ) {
109 0   0     0 return ( $b->relevance // 0 ) <=> ( $a->relevance // 0 )
110             || $a->qcode <=> $b->qcode;
111             }
112             else {
113 138   33     3763 return ( $b->relevance // 0 ) <=> ( $a->relevance // 0 )
114             || $a->qcode cmp $b->qcode;
115             }
116             }
117              
118             sub _create_subjects_location {
119 60     60   140 my $self = shift;
120 60         116 my @res;
121              
122 60 100       1729 push @res, $self->doc->createComment('locations')
123             if $self->news_item->has_locations;
124              
125 60         186 foreach my $l (
126 60         1722 sort _sort_subjects_locations values %{ $self->news_item->locations }
127             ) {
128 159 100       6008 my $why = $l->direct ? 'why:direct' : 'why:ancestor';
129 159         589 push @res,
130             my $s = $self->create_element(
131             'subject',
132             type => 'cpnat:geoArea',
133             why => $why,
134             _name_text => $l
135             );
136 159 50       7443 $s->setAttribute( 'relevance', $l->relevance )
137             if defined $l->relevance;
138 159         5459 $self->scheme_manager->add_qcode_or_literal( $s, 'geo', $l->qcode );
139 159 100       4450 if ( $l->iso_code ) {
140 53         243 $s->appendChild( my $sa = $self->create_element('sameAs') );
141 53         174 $self->scheme_manager->add_qcode_or_literal( $sa, 'iso3166_1a2',
142             $l->iso_code );
143             }
144 159 100       4697 if ( $l->parent ) {
145 106         369 $s->appendChild( my $b = $self->create_element('broader') );
146 106         305 $self->scheme_manager->add_qcode_or_literal( $b, 'geo',
147             $l->parent->qcode );
148 106         356 my $hierarchy = $self->_create_hierarchy( $l, 'geo' );
149 106 100       405 $b->appendChild($hierarchy) if $hierarchy;
150             }
151             }
152 60         218 return @res;
153             }
154              
155             sub _create_subjects_organisation {
156 60     60   147 my $self = shift;
157 60         130 my @res;
158              
159 60 100       1771 push @res, $self->doc->createComment('organisations')
160             if $self->news_item->has_organisations;
161 60         154 foreach my $org ( @{ $self->news_item->organisations } ) {
  60         1719  
162 56         254 push @res,
163             my $o = $self->create_element(
164             'subject',
165             type => 'cpnat:organisation',
166             _name_text => $org
167             );
168 56         2717 $self->scheme_manager->add_qcode_or_literal( $o, 'org', $org->qcode );
169             }
170 60         194 return @res;
171             }
172              
173             sub _create_subjects_topic {
174 60     60   164 my $self = shift;
175 60         128 my @res;
176              
177 60 100       1881 push @res, $self->doc->createComment('topics')
178             if $self->news_item->has_topics;
179              
180 60         168 foreach my $topic ( @{ $self->news_item->topics } ) {
  60         1745  
181 53         240 push @res,
182             my $t = $self->create_element(
183             'subject',
184             type => 'cpnat:abstract',
185             _name_text => $topic
186             );
187 53         2518 $self->scheme_manager->add_qcode_or_literal( $t, 'topic',
188             $topic->qcode );
189             }
190              
191 60         227 return @res;
192             }
193              
194             sub _create_subjects_product {
195 60     60   145 my $self = shift;
196 60         501 my @res;
197              
198 60 100       1839 push @res, $self->doc->createComment('products')
199             if $self->news_item->has_products;
200              
201 60         157 foreach my $product ( @{ $self->news_item->products } ) {
  60         1705  
202 53         243 push @res,
203             my $p = $self->create_element(
204             'subject',
205             type => 'cpnat:object',
206             _name_text => $product
207             );
208 53 50       2695 if ( $product->isbn ) {
    0          
209 53         1480 $self->scheme_manager->add_qcode_or_literal( $p, 'isbn',
210             $product->isbn );
211             }
212             elsif ( $product->ean ) {
213 0         0 $self->scheme_manager->add_qcode_or_literal( $p, 'ean',
214             $product->ean );
215             }
216             }
217              
218 60         199 return @res;
219             }
220              
221             sub _create_subjects_event_refs {
222 64     64   157 my $self = shift;
223              
224 64         123 my @res;
225              
226 64 100       1941 push @res, $self->doc->createComment('events')
227             if $self->news_item->has_event_references;
228              
229 64         149 foreach my $event_ref ( @{ $self->news_item->event_references } ) {
  64         1750  
230 1         25 push @res,
231             my $p = $self->create_element(
232             'subject',
233             type => 'cpnat:event',
234             _name_text => $event_ref->name
235             );
236 1         43 $self->scheme_manager->add_qcode_or_literal( $p, 'eventid',
237             $event_ref->event_id );
238             }
239 64         186 return @res;
240             }
241              
242             sub _create_subjects {
243 64     64   175 my $self = shift;
244 64         139 my @res;
245              
246 64         400 push @res, $self->_create_subjects_storytypes();
247 64         407 push @res, $self->_create_subjects_desk();
248 64         426 push @res, $self->_create_subjects_event_refs();
249 64         544 push @res, $self->_create_subjects_media_topic();
250 64 100       2063 push @res, $self->_create_subjects_concepts()
251             if ( $self->news_item->has_concepts );
252 60         426 push @res, $self->_create_subjects_location();
253 60         433 push @res, $self->_create_subjects_organisation();
254 60         392 push @res, $self->_create_subjects_topic();
255 60         434 push @res, $self->_create_subjects_product();
256              
257 60         266 return @res;
258             }
259              
260             sub _create_company_data {
261 50     50   173 my ( $self, $org, $root ) = @_;
262 50 100       1474 return unless ( $self->scheme_manager->crel );
263              
264 38         988 my $crel_alias = $self->scheme_manager->crel->alias;
265             $root->appendChild(
266             $self->create_element(
267             'related',
268             rel => "$crel_alias:index",
269             _name_text => $_
270             )
271 38         101 ) foreach ( @{ $org->indices } );
  38         1157  
272             $root->appendChild(
273             $self->create_element(
274             'related',
275             rel => "$crel_alias:exchange",
276             _name_text => $_
277             )
278 38         91 ) foreach ( @{ $org->stock_exchanges } );
  38         1169  
279 38         110 return;
280             }
281              
282             sub _create_asserts_organisation {
283 60     60   153 my $self = shift;
284              
285 60         114 my @res;
286 60 100       1926 push @res, $self->doc->createComment('organisations')
287             if $self->news_item->has_organisations;
288              
289 60         173 foreach my $org ( @{ $self->news_item->organisations } ) {
  60         1713  
290 56         231 push @res,
291             my $a = $self->create_element( 'assert', _name_text => $org );
292 56         2622 $self->scheme_manager->add_qcode_or_literal( $a, 'org', $org->qcode );
293              
294 56         145 foreach ( @{ $org->isins } ) {
  56         1825  
295 53         207 $a->appendChild( my $sa = $self->create_element('sameAs') );
296 53         176 $self->scheme_manager->add_qcode_or_literal( $sa, 'isin', $_ );
297             }
298 56 50       2765 if ( $org->has_websites ) {
299 56         230 $a->appendChild( my $od =
300             $self->create_element('organisationDetails') );
301 56         179 $od->appendChild( my $ci = $self->create_element('contactInfo') );
302             $ci->appendChild( $self->create_element( 'web', _text => $_ ) )
303 56         158 foreach @{ $org->websites };
  56         2293  
304             }
305 56         2143 $self->_create_company_data( $org, $a );
306             }
307 60         195 return @res;
308             }
309              
310             sub _create_asserts_location {
311 60     60   143 my $self = shift;
312 60         126 my @res;
313              
314 60         139 foreach my $loc_k ( sort keys %{ $self->news_item->locations } ) {
  60         1733  
315 159         9248 my $location = $self->news_item->locations->{$loc_k};
316             next
317 159 100 66     4174 unless ( defined $location->longitude
318             && defined $location->latitude );
319 53         234 push @res, my $l = $self->create_element('assert');
320 53         1475 $self->scheme_manager->add_qcode_or_literal( $l, 'geo',
321             $location->qcode );
322              
323 53         255 $l->appendChild( my $geo_area_details =
324             $self->create_element('geoAreaDetails') );
325 53         180 $geo_area_details->appendChild( my $pos =
326             $self->create_element('position') );
327              
328 53         169 $pos->setAttribute( $_, $location->$_ ) for qw/latitude longitude/;
329             }
330              
331 60         211 return @res;
332             }
333              
334             sub _create_asserts {
335 60     60   990 my $self = shift;
336 60         133 my @res;
337              
338 60         346 push @res, $self->_create_asserts_organisation();
339 60         373 push @res, $self->_create_asserts_location();
340              
341 60         197 return @res;
342             }
343              
344             sub _create_infosources {
345 57     57   186 my ( $self, $root ) = @_;
346 57         125 foreach ( @{ $self->news_item->sources } ) {
  57         1736  
347 94 100       2538 next if $_ eq uc $self->news_item->provider->qcode;
348 47         206 $root->appendChild( my $i =
349             $self->create_element( 'infoSource', _name_text => $_ ) );
350 47         1064 $self->scheme_manager->add_role( $i, 'isrol', 'originfo' );
351             }
352 57         678 return;
353             }
354              
355             sub _create_authors {
356 64     64   325 my ( $self, $root ) = @_;
357 64         146 foreach ( @{ $self->news_item->authors } ) {
  64         1965  
358 211         3145 $root->appendChild( $self->_create_creator($_) );
359             }
360 64         979 return;
361             }
362              
363             sub _create_content_meta {
364 64     64   190 my ( $self, $root ) = @_;
365              
366 64         225 my $cm = $self->create_element('contentMeta');
367              
368 64         505 $self->_create_icon($cm);
369              
370 64         2167 $cm->appendChild(
371             $self->create_element(
372             'urgency', _text => $self->news_item->priority
373             )
374             );
375              
376 64 50       212 if ( $self->news_item->content_created ) {
377 64         1913 my $t =
378             $self->_formatter->format_datetime(
379             $self->news_item->content_created );
380 64         13210 $cm->appendChild(
381             $self->create_element( 'contentCreated', _text => $t ) );
382             }
383 64 100 66     249 if ( $self->news_item->content_modified
384             and $self->news_item->content_created !=
385             $self->news_item->content_modified ) {
386 53         7011 my $t =
387             $self->_formatter->format_datetime(
388             $self->news_item->content_modified );
389 53         10383 $cm->appendChild(
390             $self->create_element( 'contentModified', _text => $t ) );
391             }
392              
393 64         557 foreach ( @{ $self->news_item->cities } ) {
  64         3032  
394 53         199 $cm->appendChild(
395             $self->create_element( 'located', _name_text => $_ ) );
396             }
397              
398 64 50       3753 if ( my $electiondistrict = $self->news_item->electiondistrict ) {
399 0         0 $cm->appendChild(
400             my $ed = $self->create_element(
401             'located', _text => $electiondistrict->name
402             )
403             );
404 0         0 $self->scheme_manager->add_qcode( $ed, 'electiondistrict',
405             $electiondistrict->qcode );
406              
407 0 0       0 if ( my $electionprovince = $electiondistrict->province ) {
408 0         0 my $ep = $self->create_element( 'located',
409             _text => $electionprovince->name );
410 0         0 $self->scheme_manager->add_qcode( $ep, 'electionprovince',
411             $electionprovince->qcode );
412              
413 0         0 $ed->appendChild($ep);
414             }
415             }
416              
417 64         458 $self->_create_infosources($cm);
418 64         423 $self->_create_authors($cm);
419              
420 64 100       1967 if ( $self->news_item->message_id ) {
421 59         4873 $cm->appendChild(
422             $self->create_element(
423             'altId', _text => $self->news_item->message_id
424             )
425             );
426             }
427              
428 64 50       317 if ( $self->news_item->byline ) {
429 0         0 $cm->appendChild(
430             $self->create_element( 'by', _text => $self->news_item->byline )
431             );
432             }
433              
434 64 50       1796 if ( $self->news_item->dateline ) {
435 0         0 $cm->appendChild(
436             $self->create_element(
437             'dateline', _text => $self->news_item->dateline
438             )
439             );
440             }
441              
442             $cm->appendChild(
443 64         1809 $self->create_element(
444             'language', tag => $self->news_item->language
445             )
446             );
447              
448 64         187 foreach ( @{ $self->news_item->genres } ) {
  64         3216  
449 106         904 $cm->appendChild( my $gn =
450             $self->create_element( 'genre', _name_text => $_ ) );
451 106         2293 $self->scheme_manager->add_qcode_or_literal( $gn, 'genre',
452             $_->qcode );
453             }
454              
455 64         1071 my @subjects = $self->_create_subjects();
456 60         763 $cm->appendChild($_) foreach (@subjects);
457              
458 60 100       7668 if ( $self->news_item->slugline ) {
459 53         1506 my $slug =
460             $self->create_element( 'slugline',
461             _text => $self->news_item->slugline );
462 53 50       1553 if ( $self->news_item->slugline_sep ) {
463 53         1522 $slug->setAttribute( 'separator',
464             $self->news_item->slugline_sep );
465             }
466 53         754 $cm->appendChild($slug);
467             }
468              
469             $cm->appendChild(
470 60         844 my $hl1 = $self->create_element(
471             'headline', _text => $self->news_item->title
472             )
473             );
474 60         165 $self->scheme_manager->add_role( $hl1, 'hltype', 'title' );
475              
476 60 100       1757 if ( $self->news_item->subtitle ) {
477 53         1519 $cm->appendChild(
478             my $hl2 = $self->create_element(
479             'headline', _text => $self->news_item->subtitle
480             )
481             );
482 53         164 $self->scheme_manager->add_role( $hl2, 'hltype', 'subtitle' );
483             }
484              
485 60 100       2640 if ( $self->news_item->credit ) {
486 53         1497 $cm->appendChild(
487             $self->create_element(
488             'creditline', _text => $self->news_item->credit
489             )
490             );
491             }
492              
493 60         184 foreach ( @{ $self->news_item->keywords } ) {
  60         2700  
494 265         4161 $cm->appendChild( $self->create_element( 'keyword', _text => $_ ) );
495             }
496              
497 60 100       2808 if ( $self->news_item->caption ) {
498 14         438 $cm->appendChild(
499             my $desc = $self->create_element(
500             'description', _text => $self->news_item->caption
501             )
502             );
503 14         47 $self->scheme_manager->add_role( $desc, 'drol', 'caption' );
504             }
505              
506 60 50       2183 if ( $self->news_item->summary ) {
507 0         0 $cm->appendChild(
508             my $smry = $self->create_element(
509             'description', _text => $self->news_item->summary
510             )
511             );
512 0         0 $self->scheme_manager->add_role( $smry, 'drol', 'summary' );
513             }
514              
515 60         457 $self->_create_teaser($cm);
516              
517 60         1007 $root->appendChild($cm);
518              
519 60         211 my @asserts = $self->_create_asserts();
520 60         701 $root->appendChild($_) foreach @asserts;
521 60         1248 return;
522             }
523              
524             sub _create_content {
525 60     60   192 my ( $self, $root ) = @_;
526              
527 60         239 $root->appendChild( my $cs = $self->create_element('contentSet') );
528 60         183 my $inlinexml = $self->create_element( 'inlineXML',
529             contenttype => 'application/xhtml+xml' );
530 60         2012 my $html = $self->create_element( 'html', _ns => $self->xhtml_ns );
531 60         1605 $html->appendChild( my $head =
532             $self->create_element( 'head', _ns => $self->xhtml_ns ) );
533 60         186 $head->appendChild(
534             $self->create_element(
535             'title',
536             _ns => $self->xhtml_ns,
537             _text => $self->news_item->title
538             )
539             );
540 60         171 $inlinexml->appendChild($html);
541              
542 60         1339 $html->appendChild( my $body =
543             $self->create_element( 'body', _ns => $self->xhtml_ns ) );
544              
545 60         169 $body->appendChild(
546             $self->create_element(
547             'h1',
548             _ns => $self->xhtml_ns,
549             _text => $self->news_item->title
550             )
551             );
552 60 100       181 $body->appendChild(
553             $self->create_element(
554             'h2',
555             _ns => $self->xhtml_ns,
556             _text => $self->news_item->subtitle
557             )
558             ) if $self->news_item->subtitle;
559              
560 60 100       327 my @paras =
561             $self->news_item->paragraphs
562             ? $self->news_item->paragraphs->getChildNodes()
563             : ();
564 60         485 $body->appendChild($_) foreach (@paras);
565              
566 60         542 $cs->appendChild($inlinexml);
567 60         168 foreach ( sort keys %{ $self->news_item->remotes } ) {
  60         6609  
568 56         714 my $rc = $self->create_element( 'remoteContent', href => $_ );
569 56         1733 $self->_create_remote_content( $rc, $self->news_item->remotes->{$_} );
570 56         939 $cs->appendChild($rc);
571             }
572 60         705 foreach ( @{ $self->news_item->inlinedata } ) {
  60         1819  
573 0         0 my %args;
574 0 0       0 if ( $_->isa('XML::NewsML_G2::Inline_CData') ) {
575 0         0 $args{_cdata} = $_->data;
576             }
577             else {
578 0         0 $args{_text} = $_->data;
579             }
580 0 0       0 $args{contenttype} = $_->mimetype if $_->mimetype;
581 0         0 my $data = $self->create_element( 'inlineData', %args );
582 0         0 $cs->appendChild($data);
583             }
584 60         203 return;
585             }
586              
587             __PACKAGE__->meta->make_immutable;
588              
589             1;
590             __END__
591              
592             =head1 NAME
593              
594             XML::NewsML_G2::Writer::News_Item - create DOM tree conforming to
595             NewsML-G2 for News Items
596              
597             =for test_synopsis
598             my ($ni, $sm);
599              
600             =head1 SYNOPSIS
601              
602             my $w = XML::NewsML_G2::Writer::News_Item->new
603             (news_item => $ni, scheme_manager => $sm);
604              
605             my $p = $w->create_element('p', class => 'main', _text => 'blah');
606              
607             my $dom = $w->create_dom();
608              
609             =head1 DESCRIPTION
610              
611             This module implements the creation of a DOM tree conforming to
612             NewsML-G2 for News Items. Depending on the version of the standard
613             specified, a version-dependent role will be applied. For the API of
614             this module, see the documentation of the superclass L<XML::NewsML_G2::Writer>.
615              
616             =head1 ATTRIBUTES
617              
618             =over 4
619              
620             =item news_item
621              
622             L<XML::NewsML_G2::News_Item> instance used to create the output document
623              
624             =back
625              
626             =head1 AUTHOR
627              
628             Philipp Gortan C<< <philipp.gortan@apa.at> >>
629              
630             =head1 LICENCE AND COPYRIGHT
631              
632             Copyright (c) 2013-2014, APA-IT. All rights reserved.
633              
634             See L<XML::NewsML_G2> for the license.