File Coverage

blib/lib/Astro/VO/VOEvent.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Astro::VO::VOEvent;
2              
3              
4             =head1 NAME
5              
6             Astro::VO::VOEvent - Object interface to parse and create VOEvent messages
7              
8             =head1 SYNOPSIS
9              
10             To parse a VOEvent file,
11              
12             $object = new Astro::VO::VOEvent( File => $file_name );
13            
14             or
15              
16             $object = new Astro::VO::VOEvent( XML => $scalar );
17            
18             Or to build a VOEVENT file,
19            
20             $xml = $object->build( %hash );
21            
22              
23             =head1 DESCRIPTION
24              
25             The module can parse VOEvent messages, and serves as a limited convenience
26             layer for building new messages. Functionality is currently very limited.
27              
28             =cut
29              
30             # L O A D M O D U L E S --------------------------------------------------
31              
32 12     12   326979 use strict;
  12         29  
  12         514  
33 12     12   94 use vars qw/ $VERSION $SELF /;
  12         21  
  12         861  
34              
35             #use XML::Parser;
36 12     12   6877 use XML::Simple;
  0            
  0            
37             use XML::Writer;
38             use XML::Writer::String;
39              
40             use Net::Domain qw(hostname hostdomain);
41             use File::Spec;
42             use Carp;
43             use Data::Dumper;
44              
45             '$Revision: 1.29 $ ' =~ /.*:\s(.*)\s\$/ && ($VERSION = $1);
46              
47             # C O N S T R U C T O R ----------------------------------------------------
48              
49             =head1 REVISION
50              
51             $Id: VOEvent.pm,v 1.29 2006/11/17 16:54:40 voevent Exp $
52              
53             =head1 METHODS
54              
55             =head2 Constructor
56              
57             =over 4
58              
59             =item B
60              
61             Create a new instance from a hash of options
62              
63             $object = new Astro::VO::VOEvent( );
64              
65             returns a reference to an VOEvent object.
66              
67             =cut
68              
69             sub new {
70             my $proto = shift;
71             my $class = ref($proto) || $proto;
72              
73             # bless the query hash into the class
74             my $block = bless { DOCUMENT => undef,
75             WRITER => undef,
76             BUFFER => undef }, $class;
77              
78             # Configure the object
79             $block->configure( @_ );
80              
81             return $block;
82              
83             }
84              
85             # A C C E S S O R M E T H O D S -------------------------------------------
86              
87             =back
88              
89             =head2 Accessor Methods
90              
91             =over 4
92              
93             =item B
94              
95             Build a VOEvent document
96              
97             $xml = $object->build( Type => $string,
98             Role => $string,
99             ID => $url,
100             Reference => { URL => $url, Type => $string } );
101              
102             or
103            
104             $xml = $object->build( Type => $string,
105             Role => $string,
106             ID => $url,
107             Description => $string,
108             Citations => [ { ID => $strig,
109             Cite => $string },
110             .
111             .
112             .
113             { ID => $string,
114             Cite => $string }],
115             Who => { Publisher => $url,
116             Contact => { Name => $string,
117             Institution => $string,
118             Address => $string,
119             Telephone => $string,
120             Email => $string, },
121             Date => $string },
122             WhereWhen => { RA => $ra,
123             Dec => $dec,
124             Error => $error,
125             Time => $time },
126             How => { Name => $string,
127             Location => $string,
128             RTML => $url,
129             Reference => { URL => $url,
130             Type => $string,
131             Name => $string } },
132             What => [ { Name => $strig,
133             UCD => $string,
134             Value => $string },
135             .
136             .
137             .
138             { Name => $string,
139             UCD => $string,
140             Value => $string } ],
141             Why => [ {Inference => {
142             Probability => $string,
143             Relation => $string,
144             Name => string
145             Concept => string }},
146             .
147             .
148             .
149             {Inference => {
150             Probability => $string,
151             Relation => $string,
152             Name => string
153             Concept => string }},
154             .
155             .
156             .
157             {Name => $string},
158             {Concept => $string } }
159             );
160            
161            
162             this will create a document from the options passed to the method, most
163             of the hash keys are optional and if missed out the relevant keywords will
164             be blank or missing entirely from the built document. Type, Role, ID and
165             either Reference or WhereWhen (and their sub-tags) are mandatory.
166              
167             The tag can be utilised from within the tag as follows
168              
169             What => [ { Group => [ { Name => $string,
170             UCD => $string,
171             Value => $string,
172             Units => $string },
173             .
174             .
175             .
176             { Name => $string,
177             UCD => $string,
178             Value => $string,
179             Units => $string } ], },
180             { Group => [ { Name => $string,
181             UCD => $string,
182             Value => $string,
183             Units => $string },
184             .
185             .
186             .
187             { Name => $string,
188             UCD => $string,
189             Value => $string,
190             Units => $string } ], },
191             { Name => $string,
192             UCD => $string,
193             Value => $string,
194             Units => $string },
195             .
196             .
197             .
198             { Name => $string,
199             UCD => $string,
200             Value => $string,
201             Units => $string } ],
202              
203             this will probably NOT be the final API for the build() method, as it is
204             overly complex. It is probably one or more convenience methods will be
205             put ontop of this routine to make it easier to use. See the t/2_simple.t
206             file in the test suite for an example which makes use of the complex form
207             of the What tag above.
208              
209             NB: This is the low level interface to build a message, this is subject
210             to change without notice as higher level "easier to use" accessor methods
211             are added to the module. It may eventually be reclassified as a PRIVATE
212             method.
213            
214             =cut
215              
216             sub build {
217             my $self = shift;
218             my %args = @_;
219              
220             # mandatory tags
221             unless ( exists $args{Role} && exists $args{ID} ) {
222             return undef;
223             }
224              
225             # open the document
226             $self->{WRITER}->xmlDecl( 'UTF-8' );
227            
228             # BEGIN DOCUMENT -------------------------------------------------------
229             if ( exists $args{UseHTN} ) {
230             $self->{WRITER}->startTag( 'VOEvent',
231             #'type' => $args{Type},
232             'role' => $args{Role},
233             'id' => $args{ID},
234             'version' => 'HTN/0.2' );
235             } elsif ( exists $args{UseQualified} ) {
236             if ( exists $args{UseID} ) {
237             $self->{WRITER}->startTag( 'VOEvent',
238             #'type' => $args{Type},
239             'role' => $args{Role},
240             'id' => $args{ID},
241             'version' => '1.1',
242             'xmlns' => 'http://www.ivoa.net/xml/VOEvent/v1.1',
243             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
244             'xsi:schemaLocation' =>
245             'http://www.ivoa.net/xml/VOEvent/v1.1 ' .
246             'http://www.ivoa.net/xml/VOEvent/VOEvent-v1.1.xsd'
247             );
248             } else {
249             $self->{WRITER}->startTag( 'VOEvent',
250             #'type' => $args{Type},
251             'role' => $args{Role},
252             'ivorn' => $args{ID},
253             'version' => '1.1',
254             'xmlns' => 'http://www.ivoa.net/xml/VOEvent/v1.1',
255             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
256             'xsi:schemaLocation' =>
257             'http://www.ivoa.net/xml/VOEvent/v1.1 ' .
258             'http://www.ivoa.net/xml/VOEvent/VOEvent-v1.1.xsd'
259             );
260             }
261             } else {
262             $self->{WRITER}->startTag( 'voe:VOEvent',
263             #'type' => $args{Type},
264             'role' => $args{Role},
265             'ivorn' => $args{ID},
266             'version' => '1.1',
267             'xmlns:voe' => 'http://www.ivoa.net/xml/VOEvent/v1.1',
268             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
269             'xsi:schemaLocation' =>
270             'http://www.ivoa.net/xml/VOEvent/v1.1 ' .
271             'http://www.ivoa.net/xml/VOEvent/VOEvent-v1.1.xsd'
272             );
273            
274             }
275            
276             # REFERENCE ONLY -------------------------------------------------------
277            
278             if ( exists $args{Reference} ) {
279             if ( exists $args{Description} ) {
280             $self->{WRITER}->startTag( 'Description' );
281             $self->{WRITER}->characters( $args{Description} );
282             $self->{WRITER}->endTag( 'Description' );
283             }
284            
285             $self->{WRITER}->emptyTag( 'Reference',
286             'uri' => ${$args{Reference}}{URL},
287             'type' => ${$args{Reference}}{Type} );
288            
289            
290             if( exists $args{UseHTN} || exists $args{UseQualified} ) {
291             $self->{WRITER}->endTag( 'VOEvent' );
292             } else {
293             $self->{WRITER}->endTag( 'voe:VOEvent' );
294             }
295             $self->{WRITER}->end();
296            
297             return $self->{BUFFER}->value();
298             }
299              
300             # SKELETON DOCUMENT ----------------------------------------------------
301              
302             # DESCRIPTION
303             if ( exists $args{Description} ) {
304             $self->{WRITER}->startTag( 'Description' );
305             $self->{WRITER}->characters( $args{Description} );
306             $self->{WRITER}->endTag( 'Description' );
307             }
308            
309             # WHO
310             if ( exists $args{Who} ) {
311             $self->{WRITER}->startTag( 'Who' );
312            
313             if ( exists ${$args{Who}}{Publisher} && ${$args{Who}}{Publisher} =~ 'ivo:' ) {
314             $self->{WRITER}->startTag( 'AuthorIVORN' );
315             $self->{WRITER}->characters( ${$args{Who}}{Publisher} );
316             $self->{WRITER}->endTag( 'AuthorIVORN' );
317             }
318            
319             my $author_flag = 0;
320             if ( exists ${$args{Who}}{Publisher} &&
321             ( ! (${$args{Who}}{Publisher} =~ 'ivo:') || exists ${$args{Who}}{Contact} ) ) {
322             $self->{WRITER}->startTag( 'Author' );
323             $author_flag = 1;
324             }
325            
326             # Backward compatible interface to older API, translate as much as possible the
327             # RTML based format into the new IVOA RM format used in v1.1
328             if ( exists ${$args{Who}}{Publisher} &&
329             ! ${$args{Who}}{Publisher} =~ 'ivo:' ) {
330             $self->{WRITER}->startTag( 'title' );
331             $self->{WRITER}->characters( ${$args{Who}}{Publisher} );
332             $self->{WRITER}->endTag( 'title' );
333             }
334             if ( exists ${$args{Who}}{Contact} ) {
335             if ( exists ${${$args{Who}}{Contact}}{Institution} ) {
336             $self->{WRITER}->startTag( 'shortName' );
337             $self->{WRITER}->characters( ${${$args{Who}}{Contact}}{Institution} );
338             $self->{WRITER}->endTag( 'shortName' );
339             }
340             if ( exists ${${$args{Who}}{Contact}}{Address} ) {
341             $self->{WRITER}->startTag( 'contributor' );
342             $self->{WRITER}->characters( ${${$args{Who}}{Contact}}{Address} );
343             $self->{WRITER}->endTag( 'contributor' );
344             }
345             if ( exists ${${$args{Who}}{Contact}}{Name} ) {
346             $self->{WRITER}->startTag( 'contactName' );
347             $self->{WRITER}->characters( ${${$args{Who}}{Contact}}{Name} );
348             $self->{WRITER}->endTag( 'contactName' );
349             }
350             if ( exists ${${$args{Who}}{Contact}}{Telephone} ) {
351             $self->{WRITER}->startTag( 'contactPhone' );
352             $self->{WRITER}->characters( ${${$args{Who}}{Contact}}{Telephone} );
353             $self->{WRITER}->endTag( 'contactPhone' );
354             }
355             if ( exists ${${$args{Who}}{Contact}}{Email} ) {
356             $self->{WRITER}->startTag( 'contactEmail' );
357             $self->{WRITER}->characters( ${${$args{Who}}{Contact}}{Email} );
358             $self->{WRITER}->endTag( 'contactEmail' );
359             }
360            
361             }
362            
363             if ( $author_flag == 1 ) {
364             $self->{WRITER}->endTag( 'Author' );
365             }
366            
367             # The new 1.1 format
368             if ( exists ${$args{Who}}{AuthorIVORN} ) {
369             $self->{WRITER}->startTag( 'AuthorIVORN' );
370             $self->{WRITER}->characters( ${$args{Who}}{AuthorIVORN} );
371             $self->{WRITER}->endTag( 'AuthorIVORN' );
372             }
373             if ( exists ${$args{Who}}{Author} ) {
374             $self->{WRITER}->startTag( 'Author' );
375             if( exists ${${$args{Who}}{Author}}{Title} ) {
376             $self->{WRITER}->startTag( 'title' );
377             $self->{WRITER}->characters( ${${$args{Who}}{Author}}{Title} );
378             $self->{WRITER}->endTag( 'title' );
379             }
380             if( exists ${${$args{Who}}{Author}}{ShortName} ) {
381             $self->{WRITER}->startTag( 'shortName' );
382             $self->{WRITER}->characters( ${${$args{Who}}{Author}}{ShortName} );
383             $self->{WRITER}->endTag( 'shortName' );
384             }
385             if( exists ${${$args{Who}}{Author}}{Contributor} ) {
386             $self->{WRITER}->startTag( 'contributor' );
387             $self->{WRITER}->characters( ${${$args{Who}}{Author}}{Contributor} );
388             $self->{WRITER}->endTag( 'contributor' );
389             }
390             if( exists ${${$args{Who}}{Author}}{LogoURL} ) {
391             $self->{WRITER}->startTag( 'logoURL' );
392             $self->{WRITER}->characters( ${${$args{Who}}{Author}}{LogoURL} );
393             $self->{WRITER}->endTag( 'logoURL' );
394             }
395             if( exists ${${$args{Who}}{Author}}{ContactName} ) {
396             $self->{WRITER}->startTag( 'contactName' );
397             $self->{WRITER}->characters( ${${$args{Who}}{Author}}{ContactName} );
398             $self->{WRITER}->endTag( 'contactName' );
399             }
400             if( exists ${${$args{Who}}{Author}}{ContactEmail} ) {
401             $self->{WRITER}->startTag( 'contactEmail' );
402             $self->{WRITER}->characters( ${${$args{Who}}{Author}}{ContactEmail} );
403             $self->{WRITER}->endTag( 'contactEmail' );
404             }
405             if( exists ${${$args{Who}}{Author}}{ContactPhone} ) {
406             $self->{WRITER}->startTag( 'contactPhone' );
407             $self->{WRITER}->characters( ${${$args{Who}}{Author}}{ContactPhone} );
408             $self->{WRITER}->endTag( 'contactPhone' );
409             }
410             $self->{WRITER}->endTag( 'Author' );
411             }
412            
413             # The tag didn't change between 1.0 and 1.1
414             if ( exists ${$args{Who}}{Date} ) {
415             $self->{WRITER}->startTag( 'Date' );
416             $self->{WRITER}->characters( ${$args{Who}}{Date} );
417             $self->{WRITER}->endTag( 'Date' );
418             }
419            
420             $self->{WRITER}->endTag( 'Who' );
421             }
422            
423             # CITATIONS
424             if ( exists $args{Citations} ) {
425             $self->{WRITER}->startTag( 'Citations' );
426            
427             my @array = @{$args{Citations}};
428             foreach my $i ( 0 ... $#array ) {
429             if ( exists $args{UseID} ) {
430             $self->{WRITER}->startTag( 'EventID','cite' => ${$array[$i]}{Cite} );
431             $self->{WRITER}->characters( ${$array[$i]}{ID} );
432             $self->{WRITER}->endTag( 'EventID' );
433             } else {
434             $self->{WRITER}->startTag( 'EventIVORN','cite' => ${$array[$i]}{Cite} );
435             $self->{WRITER}->characters( ${$array[$i]}{ID} );
436             $self->{WRITER}->endTag( 'EventIVORN' );
437             }
438             }
439             $self->{WRITER}->endTag( 'Citations' );
440             }
441            
442             # WHERE & WHEN
443             if ( exists $args{WhereWhen} ) {
444             unless ( exists $args{UseHTN} ) {
445            
446             $self->{WRITER}->startTag( 'WhereWhen' );
447             $self->{WRITER}->startTag( 'ObsDataLocation',
448             'xmlns' => 'http://www.ivoa.net/xml/STC/stc-v1.30.xsd',
449             'xmlns:xlink' => 'http://www.w3.org/1999/xlink' );
450             $self->{WRITER}->emptyTag( 'ObservatoryLocation',
451             'id' => "GEOLUN",
452             'xlink:type' => 'simple',
453             'xlink:href' => 'ivo://STClib/Observatories#GEOLUN' );
454             $self->{WRITER}->startTag( 'ObservationLocation' );
455             $self->{WRITER}->emptyTag( 'AstroCoordSystem',
456             'id' => 'UTC-FK5-GEO',
457             'xlink:type' => 'simple',
458             'xlink:href' => 'ivo://STClib/CoordSys#UTC-FK5-GEO/' );
459             $self->{WRITER}->startTag( 'AstroCoords',
460             'coord_system_id' => 'UTC-FK5-GEO' );
461             $self->{WRITER}->startTag( 'Time', 'unit' => 's' );
462             $self->{WRITER}->startTag( 'TimeInstant' );
463             $self->{WRITER}->startTag( 'ISOTime' );
464             $self->{WRITER}->characters( ${$args{WhereWhen}}{Time} );
465             $self->{WRITER}->endTag( 'ISOTime' );
466             $self->{WRITER}->endTag( 'TimeInstant' );
467             $self->{WRITER}->endTag( 'Time' );
468             $self->{WRITER}->startTag( 'Position2D', 'unit' => 'deg' );
469             $self->{WRITER}->startTag( 'Value2' );
470             $self->{WRITER}->startTag( 'C1' );
471             $self->{WRITER}->characters( ${$args{WhereWhen}}{RA} );
472             $self->{WRITER}->endTag( 'C1' );
473             $self->{WRITER}->startTag( 'C2' );
474             $self->{WRITER}->characters( ${$args{WhereWhen}}{Dec} );
475             $self->{WRITER}->endTag( 'C2' );
476             $self->{WRITER}->endTag( 'Value2' );
477             if ( exists ${$args{WhereWhen}}{Error} ) {
478             $self->{WRITER}->startTag( 'Error2Radius' );
479             $self->{WRITER}->characters( ${$args{WhereWhen}}{Error} );
480             $self->{WRITER}->endTag( 'Error2Radius' );
481             }
482             $self->{WRITER}->endTag( 'Position2D' );
483             $self->{WRITER}->endTag( 'AstroCoords' );
484             $self->{WRITER}->endTag( 'ObservationLocation' );
485             $self->{WRITER}->endTag( 'ObsDataLocation' );
486            
487             #$self->{WRITER}->startTag( 'WhereWhen' );
488             #$self->{WRITER}->startTag( 'stc:ObservationLocation' );
489             #$self->{WRITER}->startTag( 'crd:AstroCoords',
490             # 'coord_system_id' => 'FK5-UTC' );
491             #$self->{WRITER}->startTag( 'crd:Time', 'unit' => 's' );
492             #$self->{WRITER}->startTag( 'crd:TimeInstant' );
493             #$self->{WRITER}->startTag( 'crd:TimeScale' );
494             #$self->{WRITER}->characters( 'UTC' );
495             #$self->{WRITER}->endTag( 'crd:TimeScale' );
496             #$self->{WRITER}->startTag( 'crd:ISOTime' );
497             #$self->{WRITER}->characters( ${$args{WhereWhen}}{Time} );
498             #$self->{WRITER}->endTag( 'crd:ISOTime' );
499             #$self->{WRITER}->endTag( 'crd:TimeInstant' );
500             #$self->{WRITER}->endTag( 'crd:Time' );
501             #$self->{WRITER}->startTag( 'crd:Position2D', 'unit' => 'deg' );
502             #$self->{WRITER}->startTag( 'crd:Value2');
503             #my $position = ${$args{WhereWhen}}{RA} . " " . ${$args{WhereWhen}}{Dec};
504             #$self->{WRITER}->characters( $position );
505             #$self->{WRITER}->endTag( 'crd:Value2' );
506             #if ( exists ${$args{WhereWhen}}{Error} ) {
507             # $self->{WRITER}->startTag( 'crd:Error1Circle' );
508             # $self->{WRITER}->startTag( 'crd:Size' );
509             # $self->{WRITER}->characters( ${$args{WhereWhen}}{Error} );
510             # $self->{WRITER}->endTag( 'crd:Size' );
511             # $self->{WRITER}->endTag( 'crd:Error1Circle' );
512             #}
513             #$self->{WRITER}->endTag( 'crd:Position2D' );
514             #$self->{WRITER}->endTag( 'crd:AstroCoords' );
515             #$self->{WRITER}->endTag( 'stc:ObservationLocation' );
516             } else {
517             $self->{WRITER}->startTag( 'WhereWhen',
518             'type' => 'simple', );
519             $self->{WRITER}->startTag( 'RA', units => 'deg' );
520             $self->{WRITER}->startTag( 'Coord' );
521             $self->{WRITER}->characters( ${$args{WhereWhen}}{RA} );
522             $self->{WRITER}->endTag( 'Coord' );
523             if ( defined ${$args{WhereWhen}}{Error} ) {
524             $self->{WRITER}->emptyTag( 'Error',
525             value => ${$args{WhereWhen}}{Error},
526             units => "arcmin" );
527             }
528             $self->{WRITER}->endTag( 'RA' );
529             $self->{WRITER}->startTag( 'Dec', units => 'deg' );
530             $self->{WRITER}->startTag( 'Coord' );
531             $self->{WRITER}->characters( ${$args{WhereWhen}}{Dec} );
532             $self->{WRITER}->endTag( 'Coord' );
533            
534             if ( defined ${$args{WhereWhen}}{Error} ) {
535             $self->{WRITER}->emptyTag( 'Error',
536             value => ${$args{WhereWhen}}{Error},
537             units => "arcmin" );
538             }
539             $self->{WRITER}->endTag( 'Dec' );
540             $self->{WRITER}->emptyTag( 'Epoch', value => "J2000.0" );
541             $self->{WRITER}->emptyTag( 'Equinox', value => "2000.0" );
542              
543             $self->{WRITER}->startTag( 'Time' );
544             $self->{WRITER}->startTag( 'Value' );
545             $self->{WRITER}->characters( ${$args{WhereWhen}}{Time} );
546             $self->{WRITER}->endTag( 'Value' );
547             if ( exists ${$args{WhereWhen}}{TimeError} ) {
548             $self->{WRITER}->emptyTag( 'Error',
549             value => ${$args{WhereWhen}}{TimeError},
550             units => "s" );
551             }
552             $self->{WRITER}->endTag( 'Time' );
553            
554             }
555             $self->{WRITER}->endTag( 'WhereWhen' );
556             }
557            
558             # HOW
559             if ( exists $args{How} ) {
560             $self->{WRITER}->startTag( 'How' );
561            
562             #if ( exists ${$args{How}}{Name} ) {
563             # $self->{WRITER}->startTag( 'Name' );
564             # $self->{WRITER}->characters( ${$args{How}}{Name} );
565             # $self->{WRITER}->endTag( 'Name' );
566             #}
567            
568             #if ( exists ${$args{How}}{Location} ) {
569             # $self->{WRITER}->startTag( 'Location' );
570             # $self->{WRITER}->characters( ${$args{How}}{Location} );
571             # $self->{WRITER}->endTag( 'Location' );
572             #}
573             if ( exists ${$args{How}}{RTML} ) {
574             $self->{WRITER}->emptyTag( 'Reference' ,
575             uri => ${$args{How}}{RTML},
576             type => 'rtml',
577             name => 'Phase 0' );
578             }
579             if ( exists ${$args{How}}{Reference} ) {
580             $self->{WRITER}->emptyTag( 'Reference' ,
581             uri => ${${$args{How}}{Reference}}{URL},
582             type => ${${$args{How}}{Reference}}{Type},
583             name => ${${$args{How}}{Reference}}{Name} );
584             }
585            
586             $self->{WRITER}->endTag( 'How' );
587             }
588              
589             # WHAT
590             if ( exists $args{What} ) {
591             $self->{WRITER}->startTag( 'What' );
592            
593             my @array = @{$args{What}};
594             foreach my $i ( 0 ... $#array ) {
595            
596             my %hash = %{${$args{What}}[$i]};
597            
598             if ( exists $hash{Group} ) {
599             $self->{WRITER}->startTag( 'Group' );
600            
601             my @subarray = @{$hash{Group}};
602             foreach my $i ( 0 ... $#subarray ) {
603            
604             # Only UNITS is optional for Param tags
605             if ( exists ${$subarray[$i]}{Units} ) {
606             $self->{WRITER}->emptyTag('Param',
607             'name' => ${$subarray[$i]}{Name},
608             'ucd' => ${$subarray[$i]}{UCD},
609             'value' => ${$subarray[$i]}{Value},
610             'units' => ${$subarray[$i]}{Units} );
611             } else {
612             $self->{WRITER}->emptyTag('Param',
613             'name' => ${$subarray[$i]}{Name},
614             'ucd' => ${$subarray[$i]}{UCD},
615             'value' => ${$subarray[$i]}{Value},
616             'units' => ${$subarray[$i]}{Units} );
617             }
618             }
619            
620             $self->{WRITER}->endTag( 'Group' );
621            
622             } else {
623             # Only UNITS is optional for Param tags
624             if ( exists $hash{Units} ) {
625             $self->{WRITER}->emptyTag('Param',
626             'name' => $hash{Name},
627             'ucd' => $hash{UCD},
628             'value' => $hash{Value},
629             'units' => $hash{Units} );
630             } else {
631             $self->{WRITER}->emptyTag('Param',
632             'name' => $hash{Name},
633             'ucd' => $hash{UCD},
634             'value' => $hash{Value} );
635             }
636             }
637             }
638            
639             $self->{WRITER}->endTag( 'What' );
640             }
641            
642             # WHY
643             if ( exists $args{Why} ) {
644             $self->{WRITER}->startTag( 'Why' );
645            
646             my @array = @{$args{Why}};
647             foreach my $i ( 0 ... $#array ) {
648            
649             my %hash = %{${$args{Why}}[$i]};
650             if ( exists $hash{Inference} ) {
651            
652             if ( exists ${$hash{Inference}}{Relation} &&
653             exists ${$hash{Inference}}{Probability}) {
654             $self->{WRITER}->startTag( 'Inference',
655             'probability' => ${$hash{Inference}}{Probability},
656             'relation' => ${$hash{Inference}}{Relation} );
657             } elsif ( exists ${$hash{Inference}}{Probability}) {
658             $self->{WRITER}->startTag( 'Inference',
659             'probability' => ${$hash{Inference}}{Probability} );
660             } elsif ( exists ${$hash{Inference}}{Relation} ) {
661             $self->{WRITER}->startTag( 'Inference',
662             'relation' => ${$hash{Inference}}{Relation} );
663             } else {
664             $self->{WRITER}->startTag( 'Inference');
665             }
666            
667             if( exists ${$hash{Inference}}{Concept} ) {
668             $self->{WRITER}->startTag( 'Concept' );
669             $self->{WRITER}->characters( ${$hash{Inference}}{Concept} );
670             $self->{WRITER}->endTag( 'Concept' );
671             }
672            
673             if ( exists ${$hash{Inference}}{Name} ) {
674             $self->{WRITER}->startTag( 'Name' );
675             $self->{WRITER}->characters( ${$hash{Inference}}{Name} );
676             $self->{WRITER}->endTag( 'Name' );
677             }
678             $self->{WRITER}->endTag( 'Inference' );
679            
680             } elsif( exists $hash{Name} ) {
681             $self->{WRITER}->startTag( 'Name' );
682             $self->{WRITER}->characters( $hash{Name} );
683             $self->{WRITER}->endTag( 'Name' );
684            
685             } elsif( exists $hash{Concept} ) {
686             $self->{WRITER}->startTag( 'Concept' );
687             $self->{WRITER}->characters( $hash{Concept} );
688             $self->{WRITER}->endTag( 'Concept' );
689              
690             }
691             }
692            
693             $self->{WRITER}->endTag( 'Why' );
694            
695             }
696            
697             # END DOCUMENT ---------------------------------------------------------
698             if( exists $args{UseHTN} || exists $args{UseQualified} ) {
699             $self->{WRITER}->endTag( 'VOEvent' );
700             } else {
701             $self->{WRITER}->endTag( 'voe:VOEvent' );
702             }
703             $self->{WRITER}->end();
704            
705             my $xml = $self->{BUFFER}->value();
706             $self->_parse( XML => $xml );
707             return $xml;
708            
709            
710             }
711              
712             =item B
713              
714             Return the id of the VOEvent document
715              
716             $object = new Astro::VO::VOEvent( XML => $scalar );
717             $id = $object->id();
718            
719             =cut
720              
721             sub id {
722             my $self = shift;
723              
724             my $id;
725             if ( defined $self->{DOCUMENT}->{ivorn} ) {
726             $id = $self->{DOCUMENT}->{ivorn};
727             } else {
728             $id = $self->{DOCUMENT}->{id};
729             }
730             return $id;
731             }
732              
733             =item B
734              
735             Return the role of the VOEvent document
736              
737             $object = new Astro::VO::VOEvent( XML => $scalar );
738             $id = $object->role();
739            
740             =cut
741              
742             sub role {
743             my $self = shift;
744             return $self->{DOCUMENT}->{role};
745             }
746              
747             =item B
748              
749             Return the version of the VOEvent document
750              
751             $object = new Astro::VO::VOEvent( XML => $scalar );
752             $version = $object->version();
753            
754             =cut
755              
756             sub version {
757             my $self = shift;
758             return $self->{DOCUMENT}->{version};
759             }
760              
761              
762             =item B
763              
764             Return the human readable description from the VOEvent document
765              
766             $object = new Astro::VO::VOEvent( XML => $scalar );
767             $string = $object->description();
768            
769             =cut
770              
771             sub description {
772             my $self = shift;
773             return $self->{DOCUMENT}->{Description};
774             }
775              
776             =item B{ra}
777              
778             Return the RA of the object as given in the tag
779              
780             $object = new Astro::VO::VOEvent( XML => $scalar );
781             $ra = $object->ra();
782              
783             =cut
784              
785             sub ra {
786             my $self = shift;
787            
788             my %ra;
789             if ( defined $self->{DOCUMENT}->{WhereWhen}->{type} &&
790             $self->{DOCUMENT}->{WhereWhen}->{type} eq "simple" ) {
791            
792             if( defined $self->{DOCUMENT}->{WhereWhen}->{RA}->{Coord} ) {
793             $ra{value} = $self->{DOCUMENT}->{WhereWhen}->{RA}->{Coord};
794             } elsif ( defined $self->{DOCUMENT}->{WhereWhen}->{Ra}->{Coord} ) {
795             $ra{value} = $self->{DOCUMENT}->{WhereWhen}->{Ra}->{Coord};
796             }
797             $ra{units} = $self->{DOCUMENT}->{WhereWhen}->{RA}->{units};
798             $ra{error} = {"value" => $self->{DOCUMENT}->{WhereWhen}->{RA}->{Error}{value},
799             "units" => $self->{DOCUMENT}->{WhereWhen}->{RA}->{Error}{units}};
800             } else {
801            
802             #print Dumper( $self->{DOCUMENT}->{WhereWhen} );
803            
804             # Try old style eSTAR default
805             my $string = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObservationLocation"}->
806             {"crd:AstroCoords"}->{"crd:Position2D"}->{"crd:Value2"};
807             my ($ra, $dec) = split " ", $string if defined $string;
808            
809             $ra{value} = $ra;
810             $ra{units} = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObservationLocation"}->
811             {"crd:AstroCoords"}->{"crd:Position2D"}->{unit};
812              
813             # Try RAPTOR default
814             unless ( defined $ra{value} ) {
815             $ra{value} = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObsDataLocation"}
816             ->{"stc:ObservationLocation"}->{"stc:AstroCoords"}->{"stc:Position2D"}
817             ->{"stc:Value2"}->{"stc:C1"};
818            
819             $ra{units} = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObsDataLocation"}
820             ->{"stc:ObservationLocation"}->{"stc:AstroCoords"}->{"stc:Position2D"}
821             ->{unit};
822             }
823            
824             # Try new style v1.1 default
825             unless ( defined $ra{value} ) {
826             $ra{value} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
827             ->{'ObservationLocation'}->{'AstroCoords'}->{'Position2D'}
828             ->{'Value2'}->{'C1'};
829              
830             $ra{units} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
831             ->{'ObservationLocation'}->{'AstroCoords'}->{'Position2D'}
832             ->{unit};
833             }
834              
835             # Try new style v1.1 default with the
836             # and the tags added into the path.
837             unless ( defined $ra{value} ) {
838             $ra{value} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
839             ->{'ObservatoryLocation'}->{'ObservationLocation'}
840             ->{'AstroCoordSystem'}->{'AstroCoords'}
841             ->{'Position2D'}->{'Value2'}->{'C1'};
842              
843             $ra{units} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
844             ->{'ObservatoryLocation'}->{'ObservationLocation'}
845             ->{'AstroCoordSystem'}->{'AstroCoords'}
846             ->{'Position2D'}->{unit};
847             }
848              
849             }
850            
851             return ( wantarray ? %ra : $ra{"value"} );
852             }
853              
854              
855             =item B{dec}
856              
857             Return the Dec of the object as given in the tag
858              
859             $object = new Astro::VO::VOEvent( XML => $scalar );
860             $dec = $object->dec();
861              
862             =cut
863              
864             sub dec {
865             my $self = shift;
866            
867             my %dec;
868             if ( defined $self->{DOCUMENT}->{WhereWhen}->{type} &&
869             $self->{DOCUMENT}->{WhereWhen}->{type} eq "simple" ) {
870            
871              
872             $dec{value} = $self->{DOCUMENT}->{WhereWhen}->{Dec}->{Coord};
873             $dec{units} = $self->{DOCUMENT}->{WhereWhen}->{Dec}->{units};
874             $dec{error} = {"value"=>$self->{DOCUMENT}->{WhereWhen}->{Dec}->{Error}{value},
875             "units"=>$self->{DOCUMENT}->{WhereWhen}->{Dec}->{Error}{units}};
876             } else {
877            
878             # Try old style eSTAR default
879             my $string = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObservationLocation"}->
880             {"crd:AstroCoords"}->{"crd:Position2D"}->{"crd:Value2"};
881             my ($ra, $dec) = split " ", $string if defined $string;
882            
883             $dec{value} = $dec;
884             $dec{units} = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObservationLocation"}->
885             {"crd:AstroCoords"}->{"crd:Position2D"}->{unit};
886              
887              
888             # Try RAPTOR default
889             unless ( defined $dec{value} ) {
890             $dec{value} = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObsDataLocation"}
891             ->{"stc:ObservationLocation"}->{"stc:AstroCoords"}->{"stc:Position2D"}
892             ->{"stc:Value2"}->{"stc:C2"};
893            
894             $dec{units} = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObsDataLocation"}
895             ->{"stc:ObservationLocation"}->{"stc:AstroCoords"}->{"stc:Position2D"}
896             ->{unit};
897            
898             }
899            
900             # Try new style v1.1 default
901             unless ( defined $dec{value} ) {
902             $dec{value} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
903             ->{'ObservationLocation'}->{'AstroCoords'}->{'Position2D'}
904             ->{'Value2'}->{'C2'};
905              
906             $dec{units} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
907             ->{'ObservationLocation'}->{'AstroCoords'}->{'Position2D'}
908             ->{unit};
909             }
910              
911              
912             # Try new style v1.1 default with the
913             # and the tags added into the path.
914             unless ( defined $dec{value} ) {
915             $dec{value} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
916             ->{'ObservatoryLocation'}->{'ObservationLocation'}
917             ->{'AstroCoordSystem'}->{'AstroCoords'}
918             ->{'Position2D'}->{'Value2'}->{'C2'};
919              
920             $dec{units} = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
921             ->{'ObservatoryLocation'}->{'ObservationLocation'}
922             ->{'AstroCoordSystem'}->{'AstroCoords'}
923             ->{'Position2D'}->{unit};
924             }
925              
926             }
927            
928             return ( wantarray ? %dec : $dec{"value"} );
929             }
930              
931             =item B{epoch}
932              
933             Return the Dec of the object as given in the tag
934              
935             $object = new Astro::VO::VOEvent( XML => $scalar );
936             $epoch = $object->epoch();
937              
938             =cut
939              
940             sub epoch {
941             my $self = shift;
942            
943             if ( defined $self->{DOCUMENT}->{WhereWhen}->{type} &&
944             $self->{DOCUMENT}->{WhereWhen}->{type} eq "simple" ) {
945             return $self->{DOCUMENT}->{WhereWhen}->{Epoch}->{value};
946             } else {
947            
948             # old style eSTAR default
949             my $string = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObservationLocation"}->
950             {"crd:AstroCoords"}->{"coord_system_id"};
951            
952             # RAPTOR default
953             unless (defined $string ) {
954             $string = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObsDataLocation"}
955             ->{"stc:ObservationLocation"}->{"stc:AstroCoords"}
956             ->{"coord_system_id"};
957             }
958            
959             # new style v1.1 default
960             unless ( defined $string ) {
961             $string = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
962             ->{'ObservationLocation'}->{'AstroCoords'}->{"coord_system_id"};
963             }
964              
965             # Try new style v1.1 default with and
966             # tags
967             unless ( defined $string ) {
968             $string = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
969             ->{'ObservatoryLocation'}->{'ObservationLocation'}
970             ->{'AstroCoordSystem'}->{'AstroCoords'}
971             ->{"coord_system_id"};
972             }
973            
974             if( $string =~ "FK5" ) {
975             return "J2000.0";
976             } else {
977             return undef;
978             }
979             }
980             }
981              
982              
983             =item B{equinox}
984              
985             Return the Dec of the object as given in the tag
986              
987             $object = new Astro::VO::VOEvent( XML => $scalar );
988             $equinox = $object->equinox();
989              
990             =cut
991              
992             sub equinox {
993             my $self = shift;
994            
995             if ( defined $self->{DOCUMENT}->{WhereWhen}->{type} &&
996             $self->{DOCUMENT}->{WhereWhen}->{type} eq "simple" ) {
997             return $self->{DOCUMENT}->{WhereWhen}->{Equinox}->{value};
998             } else {
999            
1000             # eSTAR default
1001             my $string = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObservationLocation"}->
1002             {"crd:AstroCoords"}->{"coord_system_id"};
1003            
1004             # RAPTOR default
1005             unless (defined $string ) {
1006             $string = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObsDataLocation"}
1007             ->{"stc:ObservationLocation"}->{"stc:AstroCoords"}
1008             ->{"coord_system_id"};
1009             }
1010            
1011             # new style v1.1 default
1012             unless ( defined $string ) {
1013             $string = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
1014             ->{'ObservationLocation'}->{'AstroCoords'}->{"coord_system_id"};
1015             }
1016              
1017             # Try new style v1.1 default with and
1018             # the tags
1019             unless ( defined $string ) {
1020             $string = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
1021             ->{'ObservatoryLocation'}->{'ObservationLocation'}
1022             ->{'AstroCoordSystem'}->{'AstroCoords'}
1023             ->{"coord_system_id"};
1024             }
1025            
1026             if( $string =~ "FK5" ) {
1027             return "2000.0";
1028             } else {
1029             return undef;
1030             }
1031             }
1032             }
1033              
1034             =item B{time}
1035              
1036             Return the Time of the object as given in the tag
1037              
1038             $object = new Astro::VO::VOEvent( XML => $scalar );
1039             $time = $object->time();
1040              
1041             =cut
1042              
1043             sub time {
1044             my $self = shift;
1045            
1046             my $time;
1047             if ( defined $self->{DOCUMENT}->{WhereWhen}->{type} &&
1048             $self->{DOCUMENT}->{WhereWhen}->{type} eq "simple" ) {
1049            
1050             $time = $self->{DOCUMENT}->{WhereWhen}->{Time}->{Value};
1051            
1052             } else {
1053            
1054             # old style eSTAR default
1055             $time = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObservationLocation"}->
1056             {"crd:AstroCoords"}->{"crd:Time"}->{"crd:TimeInstant"}->{"crd:ISOTime"};
1057            
1058             # RAPTOR default
1059             unless ( defined $time ) {
1060            
1061             $time = $self->{DOCUMENT}->{WhereWhen}->{"stc:ObsDataLocation"}
1062             ->{"stc:ObservationLocation"}->{"stc:AstroCoords"}
1063             ->{"stc:Time"}->{"stc:TimeInstant"}->{"stc:ISOTime"};
1064            
1065             }
1066            
1067             # new style v1.1 default
1068             unless ( defined $time ) {
1069             $time = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
1070             ->{'ObservationLocation'}->{'AstroCoords'}->{"Time"}
1071             ->{"TimeInstant"}->{"ISOTime"};
1072             }
1073            
1074              
1075             # Try new style v1.1 default with and
1076             # the tags
1077             unless ( defined $time ) {
1078             $time = $self->{DOCUMENT}->{WhereWhen}->{'ObsDataLocation'}
1079             ->{'ObservatoryLocation'}->{'ObservationLocation'}
1080             ->{'AstroCoordSystem'}->{'AstroCoords'}
1081             ->{"Time"}->{"TimeInstant"}->{"ISOTime"};
1082             }
1083             }
1084            
1085             # There isn't a (valid?) see if there is a timestamp in
1086             # the tag as this might also carry a publication datestamp.
1087             unless ( defined $time ) {
1088             $time = $self->{DOCUMENT}->{Who}->{Date};
1089             }
1090            
1091             return $time;
1092             }
1093              
1094              
1095             =item B{what}
1096              
1097             Return the and 's of s in the tag,
1098              
1099             $object = new Astro::VO::VOEvent( XML => $scalar );
1100             %what = $object->what();
1101              
1102             =cut
1103              
1104             sub what {
1105             my $self = shift;
1106             if ( defined $self->{DOCUMENT}->{What} ) {
1107             return %{$self->{DOCUMENT}->{What}};
1108             } else {
1109             return undef;
1110             }
1111             }
1112              
1113             # C O N F I G U R E ---------------------------------------------------------
1114              
1115             =back
1116              
1117             =head2 General Methods
1118              
1119             =over 4
1120              
1121             =item B
1122              
1123             Configures the object, takes an options hash as an argument
1124              
1125             $rtml->configure( %options );
1126              
1127             does nothing if the hash is not supplied.
1128              
1129             =cut
1130              
1131             sub configure {
1132             my $self = shift;
1133              
1134             # BLESS XML WRITER
1135             # ----------------
1136             $self->{BUFFER} = new XML::Writer::String();
1137             $self->{WRITER} = new XML::Writer( OUTPUT => $self->{BUFFER},
1138             DATA_MODE => 1,
1139             DATA_INDENT => 4 );
1140            
1141             # CONFIGURE FROM ARGUEMENTS
1142             # -------------------------
1143              
1144             # return unless we have arguments
1145             return undef unless @_;
1146              
1147             # grab the argument list
1148             my %args = @_;
1149            
1150             # Loop over the allowed keys
1151             for my $key (qw / File XML / ) {
1152             if ( lc($key) eq "file" && exists $args{$key} ) {
1153             $self->_parse( File => $args{$key} );
1154             last;
1155            
1156             } elsif ( lc($key) eq "xml" && exists $args{$key} ) {
1157             $self->_parse( XML => $args{$key} );
1158             last;
1159            
1160             }
1161             }
1162              
1163             # Nothing to configure...
1164             return undef;
1165              
1166             }
1167              
1168             # T I M E A T T H E B A R --------------------------------------------
1169              
1170             =back
1171              
1172             =head1 COPYRIGHT
1173              
1174             Copyright (C) 2002 University of Exeter. All Rights Reserved.
1175              
1176             This program was written as part of the eSTAR project and is free software;
1177             you can redistribute it and/or modify it under the terms of the GNU Public
1178             License.
1179              
1180             =head1 AUTHORS
1181              
1182             Alasdair Allan Eaa@astro.ex.ac.ukE,
1183              
1184             =cut
1185              
1186             # P R I V A T E M E T H O D S ------------------------------------------
1187              
1188             =begin __PRIVATE_METHODS__
1189              
1190             =head2 Private Methods
1191              
1192             These methods are for internal use only.
1193              
1194             =over 4
1195              
1196             =item B<_parse>
1197              
1198             Private method to parse a VOEvent document
1199              
1200             $object->_parse( File => $file_name );
1201             $object->_parse( XML => $scalar );
1202              
1203             this should not be called directly
1204             =cut
1205              
1206             sub _parse {
1207             my $self = shift;
1208              
1209             # return unless we have arguments
1210             return undef unless @_;
1211              
1212             # grab the argument list
1213             my %args = @_;
1214              
1215             my $xs = new XML::Simple( );
1216              
1217             # Loop over the allowed keys
1218             for my $key (qw / File XML / ) {
1219             if ( lc($key) eq "file" && exists $args{$key} ) {
1220             $self->{DOCUMENT} = $xs->XMLin( $args{$key} );
1221             last;
1222            
1223             } elsif ( lc($key) eq "xml" && exists $args{$key} ) {
1224             $self->{DOCUMENT} = $xs->XMLin( $args{$key} );
1225             last;
1226            
1227             }
1228             }
1229            
1230             #print Dumper( $self->{DOCUMENT} );
1231             return;
1232             }
1233              
1234             # L A S T O R D E R S ------------------------------------------------------
1235              
1236             1;