File Coverage

blib/lib/XML/Document/RTML.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 XML::Document::RTML;
2             # ---------------------------------------------------------------------------
3              
4             #+
5             # Name:
6             # XML::Document::RTML
7              
8             # Purposes:
9             # Perl module to build and parse RTML documents
10              
11             # Language:
12             # Perl module
13              
14             # Authors:
15             # Alasdair Allan (aa@astro.ex.ac.uk)
16              
17             # Revision:
18             # $Id: RTML.pm,v 1.16 2006/11/17 20:43:26 aa Exp $
19              
20             # Copyright:
21             # Copyright (C) 200s University of Exeter. All Rights Reserved.
22              
23             #-
24              
25             # ---------------------------------------------------------------------------
26              
27             =head1 NAME
28              
29             XML::Document::RTML - module which builds and parses RTML documents
30              
31             =head1 SYNOPSIS
32              
33             An object instance can be created from an existing RTML document in a
34             scalar, or directly from a file on local disk.
35              
36              
37             my $object = new XML::Document::RTML( XML => $xml );
38             my $object = new XML::Document::RTML( File => $file );
39            
40             or via the build method,
41              
42             my $object = new XML::Document::RTML()
43             $document = $object->build( %hash );
44            
45             once instantiated various query methods are supported, e.g.,
46              
47             my $object = new XML::Document::RTML( File => $file );
48             my $role = $object->role();
49              
50             =head1 DESCRIPTION
51              
52             The module can build and parse RTML documents. Currently only version 2.2
53             of the standard is supported by the module.
54              
55             =cut
56             # L O A D M O D U L E S --------------------------------------------------
57              
58 7     7   183776 use strict;
  7         38  
  7         398  
59 7     7   43 use vars qw/ $VERSION $SELF /;
  7         31  
  7         577  
60              
61 7     7   4799 use XML::Simple;
  0            
  0            
62             use XML::Writer;
63             use XML::Writer::String;
64              
65             use Net::Domain qw(hostname hostdomain);
66             use File::Spec;
67             use Carp;
68             use Data::Dumper;
69             use Scalar::Util qw(reftype);
70              
71             #use Astro::FITS::Header;
72             #use Astro::VO::VOTable;
73              
74             '$Revision: 1.16 $ ' =~ /.*:\s(.*)\s\$/ && ($VERSION = $1);
75              
76             # C O N S T R U C T O R ----------------------------------------------------
77              
78             =head1 REVISION
79              
80             $Id: RTML.pm,v 1.16 2006/11/17 20:43:26 aa Exp $
81              
82             =head1 METHODS
83              
84             =head2 Constructor
85              
86             =over 4
87              
88             =item B
89              
90             Create a new instance from a hash of options
91              
92             my $object = new XML::Document::RTML( %hash );
93              
94             returns a reference to an message object.
95              
96             =cut
97              
98              
99             sub new {
100             my $proto = shift;
101             my $class = ref($proto) || $proto;
102              
103             # bless the query hash into the class
104             my $block = bless { DOCUMENT => undef, # hash generated by XML::Simple
105             WRITER => undef, # reference to an XML::Writer
106             BUFFER => undef, # reference to an XML::Writer::String
107             DTD => undef
108             }, $class;
109              
110             # Configure the object
111             $block->configure( @_ );
112              
113             return $block;
114              
115             }
116              
117             # B U I L D M E T H O D ------------------------------------------------
118              
119             sub build {
120             my $self = shift;
121             my %args = @_;
122              
123             # mandatory tags
124             unless ( exists $args{Type} ) {
125             return undef;
126             }
127            
128             # Loop over the rest of the keys
129             for my $key (qw / Role Type Version DTD GroupCount ExposureTime Exposure
130             SignalToNoise Snr Flux ExposureType ExposureUnits
131             SeriesCount Interval Tolerance Priority TimeConstraint
132             DeviceType Device FilterType Filter TargetType TargetIdent
133             Identity TargetName Target CoordinateType Coordtype
134             RA RAFormat RAUnits Dec DecFormat DecUnits Equinox
135             Host Port PortNumber ID UniqueID Name ObserverName
136             RealName User UserName Institution Email EmailAddress
137             Project Score CompletionTime Time Data / ) {
138             my $method = lc($key);
139             $self->$method( $args{$key} ) if exists $args{$key};
140             }
141              
142             # open the document
143             $self->{WRITER}->xmlDecl( 'ISO-8859-1' );
144            
145             # BEGIN DOCUMENT -------------------------------------------------------
146            
147             if ( $self->version() == 2.2 ) {
148             $self->{WRITER}->doctype( 'RTML', '', $self->{DTD} );
149             } elsif ( $self->version() == 2.1 ) {
150             $self->{WRITER}->doctype( 'RTML', '',
151             "http://astro.livjm.ac.uk/HaGS/rtml2.1.dtd" );
152             } else {
153             $self->{WRITER}->doctype( 'RTML' );
154             }
155            
156             # open the RTML document
157             # ======================
158             $self->{WRITER}->startTag( 'RTML','version' => $self->version(),
159             'type' => $self->type() );
160            
161             # Contact Tag
162             # -----------
163             if( defined $self->user_name() ||
164             defined $self->real_name() ||
165             defined $self->institution() ||
166             defined $self->email() ) {
167            
168             $self->{WRITER}->startTag( 'Contact', 'PI' => 'true' );
169              
170             if (defined $self->real_name() ) {
171            
172             $self->{WRITER}->startTag( 'Name');
173             $self->{WRITER}->characters( $self->real_name() );
174             $self->{WRITER}->endTag( 'Name' );
175             } else {
176             $self->{WRITER}->emptyTag( 'Name');
177             }
178             if (defined $self->user_name() ) {
179             $self->{WRITER}->startTag( 'User');
180             $self->{WRITER}->characters( $self->user_name() );
181             $self->{WRITER}->endTag( 'User' );
182             } else {
183             $self->{WRITER}->emptyTag( 'User');
184             }
185             if (defined $self->institution() ) {
186            
187             $self->{WRITER}->startTag( 'Institution');
188             $self->{WRITER}->characters( $self->institution() );
189             $self->{WRITER}->endTag( 'Institution' );
190             } else {
191             $self->{WRITER}->emptyTag( 'Institution');
192             }
193             if (defined $self->email() ) {
194            
195             $self->{WRITER}->startTag( 'Email');
196             $self->{WRITER}->characters( $self->email() );
197             $self->{WRITER}->endTag( 'Email' );
198             } else {
199             $self->{WRITER}->emptyTag( 'Email');
200             }
201            
202             $self->{WRITER}->endTag( 'Contact' );
203             } else {
204             $self->{WRITER}->emptyTag( 'Contact' );
205             }
206            
207             # Project Tag
208             # -----------
209             if (defined $self->project() ) {
210             $self->{WRITER}->startTag( 'Project' );
211             $self->{WRITER}->characters( $self->project() );
212             $self->{WRITER}->endTag( 'Project' );
213             } else {
214             $self->{WRITER}->emptyTag( 'Project' );
215             }
216              
217             # Telescope Tag
218             # -------------
219             $self->{WRITER}->emptyTag( 'Telescope' );
220              
221             # IntelligentAgent Tag
222             # --------------------
223              
224             if (defined $self->id() && defined $self->host() && defined $self->port() ) {
225              
226             $self->{WRITER}->startTag( 'IntelligentAgent',
227             'host' => $self->host(), 'port' => $self->port() );
228            
229             $self->{WRITER}->characters( $self->id() );
230            
231             $self->{WRITER}->endTag( 'IntelligentAgent' );
232             }
233            
234             # Observation tag
235             # ---------------
236             $self->{WRITER}->startTag( 'Observation', 'status' => 'ok' );
237            
238             # Target
239             # ------
240             $self->{WRITER}->startTag( 'Target', ,
241             'type' => $self->target_type(),
242             'ident' => $self->target_ident() );
243            
244             # Target Name
245             # -----------
246             if ( defined $self->target() ) {
247             $self->{WRITER}->startTag( 'TargetName' );
248             $self->{WRITER}->characters( $self->target() );
249             $self->{WRITER}->endTag( 'TargetName' );
250             } else {
251             $self->{WRITER}->emptyTag( 'TargetName' );
252             }
253            
254             # Co-ordinates
255             # ------------
256             if ( defined $self->coordinate_type() ) {
257             $self->{WRITER}->startTag( 'Coordinates',
258             'type' => $self->coordinate_type());
259             } else {
260             $self->{WRITER}->startTag( 'Coordinates' );
261             }
262             $self->{WRITER}->startTag( 'RightAscension',
263             'format' => $self->raformat(),
264             'units' => $self->raunits() );
265             $self->{WRITER}->characters( $self->ra() );
266             $self->{WRITER}->endTag( 'RightAscension' );
267            
268             $self->{WRITER}->startTag( 'Declination',
269             'format' => $self->decformat(),
270             'units' => $self->decunits() );
271             if ( $self->dec() =~ m/^\+/ ) {
272             $self->{WRITER}->characters( $self->dec() );
273             } else {
274             if ( $self->dec() =~ m/-/ ) {
275             $self->{WRITER}->characters( $self->dec() );
276             } else {
277             $self->{WRITER}->characters( "+" . $self->dec() );
278             }
279             }
280             $self->{WRITER}->endTag( 'Declination' );
281              
282             $self->{WRITER}->startTag( 'Equinox' );
283             $self->{WRITER}->characters( $self->equinox() );
284             $self->{WRITER}->endTag( 'Equinox' );
285              
286             $self->{WRITER}->endTag( 'Coordinates' );
287              
288            
289             # Flux
290             # ----
291             if( $self->exposure_type() eq "snr" ) {
292            
293             $self->{WRITER}->startTag( 'Flux',
294             'type' => 'continuum',
295             'units' => 'mag',
296             'wavelength' => $self->filter_type() );
297             $self->{WRITER}->characters( $self->reference_flux() );
298             $self->{WRITER}->endTag( 'Flux' );
299             }
300            
301             $self->{WRITER}->endTag( 'Target' );
302            
303             # Device
304             # ------
305             $self->{WRITER}->startTag( 'Device', 'type' => $self->device_type() );
306            
307             # Filter
308             # ------
309             $self->{WRITER}->startTag( 'Filter' );
310             $self->{WRITER}->startTag( 'FilterType');
311             $self->{WRITER}->characters( $self->filter_type() );
312             $self->{WRITER}->endTag( 'FilterType' );
313             $self->{WRITER}->endTag( 'Filter' );
314             $self->{WRITER}->endTag( 'Device' );
315            
316             # Schedule
317             # --------
318             $self->{WRITER}->startTag( 'Schedule', 'priority' => $self->priority() );
319            
320             # Exposure
321             # --------
322             if ( $self->exposure_type() eq "time" ) {
323             $self->{WRITER}->startTag( 'Exposure',
324             'type' => $self->exposure_type(),
325             'units' => $self->exposure_units() );
326             if( defined $self->group_count() && $self->group_count() > 1 ) {
327             $self->{WRITER}->startTag( 'Count');
328             $self->{WRITER}->characters( $self->group_count() );
329             $self->{WRITER}->endTag( 'Count' );
330             }
331             $self->{WRITER}->characters( $self->exposure_time() );
332            
333             } else {
334             $self->exposure_type( "snr" );
335             $self->{WRITER}->startTag( 'Exposure',
336             'type' => $self->exposure_type() );
337             if( defined $self->group_count() && $self->group_count() > 1 ) {
338             $self->{WRITER}->startTag( 'Count');
339             $self->{WRITER}->characters( $self->group_count() );
340             $self->{WRITER}->endTag( 'Count' );
341             }
342             $self->{WRITER}->characters( $self->signal_to_noise() );
343            
344             }
345             $self->{WRITER}->endTag( 'Exposure' );
346            
347             # TimeConstraint
348             # --------------
349             if( defined $self->start_time() && defined $self->end_time() ) {
350             $self->{WRITER}->startTag( 'TimeConstraint' );
351             $self->{WRITER}->startTag( 'StartDateTime' );
352             $self->{WRITER}->characters( $self->start_time() );
353             $self->{WRITER}->endTag( 'StartDateTime' );
354             $self->{WRITER}->startTag( 'EndDateTime' );
355             $self->{WRITER}->characters( $self->end_time() );
356             $self->{WRITER}->endTag( 'EndDateTime' );
357             $self->{WRITER}->endTag( 'TimeConstraint' );
358             }
359            
360             # SeriesConstraint
361             # ----------------
362             if ( defined $self->series_count() &&
363             defined $self->interval() &&
364             defined $self->tolerance() ) {
365            
366             $self->{WRITER}->startTag( 'SeriesConstraint' );
367            
368             $self->{WRITER}->startTag( 'Count' );
369             $self->{WRITER}->characters($self->series_count() );
370             $self->{WRITER}->endTag( 'Count' );
371            
372             $self->{WRITER}->startTag( 'Interval' );
373             $self->{WRITER}->characters( $self->interval() );
374             $self->{WRITER}->endTag( 'Interval' );
375            
376             $self->{WRITER}->startTag( 'Tolerance' );
377             $self->{WRITER}->characters( $self->tolerance() );
378             $self->{WRITER}->endTag( 'Tolerance' );
379            
380             $self->{WRITER}->endTag( 'SeriesConstraint' );
381             }
382            
383             $self->{WRITER}->endTag( 'Schedule' );
384              
385             # Data tags
386             # ---------
387             my @images = $self->images();
388             my @image_type = $self->image_type();
389             my @image_delivery = $self->image_delivery();
390             my @image_reduced = $self->image_reduced();
391            
392             my @catalogues = $self->catalogues();
393             my @catalogue_types = $self->catalogue_type();
394            
395             my @headers = $self->headers();
396             my @header_types = $self->header_type();
397            
398             foreach my $j ( 0 .. $#images ) {
399            
400             $self->{WRITER}->startTag( 'ImageData',
401             'type' => $image_type[$j],
402             'delivery' => $image_delivery[$j],
403             'reduced' => $image_reduced[$j] );
404            
405             # FITSHeader
406             # ----------
407             if( defined $headers[$j] && defined $header_types[$j] ) {
408             $self->{WRITER}->startTag( 'FITSHeader', 'type' => $header_types[$j] );
409             $self->{WRITER}->characters( $headers[$j] );
410             $self->{WRITER}->endTag( 'FITSHeader' );
411             }
412              
413             # ObjectList
414             # ----------
415             if ( defined $catalogues[$j] && defined $catalogue_types[$j] ) {
416             $self->{WRITER}->startTag( 'ObjectList', 'type' => $catalogue_types[$j] );
417             $self->{WRITER}->characters( $catalogues[$j] );
418             $self->{WRITER}->endTag( 'ObjectList' );
419             }
420            
421             # FITS file
422             # ---------
423             $self->{WRITER}->characters( $images[$j] );
424            
425             $self->{WRITER}->endTag( 'ImageData' );
426             }
427            
428             $self->{WRITER}->endTag( 'Observation' );
429            
430             # Score Tags
431             # ----------
432             if (defined $self->{DOCUMENT}->{Score} ) {
433             $self->{WRITER}->startTag( 'Score' );
434             $self->{WRITER}->characters( $self->{DOCUMENT}->{Score} );
435             $self->{WRITER}->endTag( 'Score' );
436             }
437             if ( defined $self->{DOCUMENT}->{CompletionTime} ) {
438             $self->{WRITER}->startTag( 'CompletionTime' );
439             $self->{WRITER}->characters( $self->{DOCUMENT}->{CompletionTime} );
440             $self->{WRITER}->endTag( 'CompletionTime' );
441             }
442            
443             # close the RTML DOCUMENT
444             # =======================
445              
446             $self->{WRITER}->endTag( 'RTML' );
447             $self->{WRITER}->end();
448              
449             # END DOCUMENT --------------------------------------------------------
450              
451             my $xml = $self->{BUFFER}->value();
452             $self->_parse( XML => $xml ); # populates the object with a parsed document
453             return $xml;
454              
455             }
456              
457             # A C C E S S O R M E T H O D S -------------------------------------------
458              
459             =back
460              
461             =head2 Accessor Methods
462              
463             =over 4
464              
465             =item B
466              
467             Return, or set, the type of the RTML document
468              
469             my $type = $object->type();
470             $object->type( $type );
471              
472             =cut
473              
474             sub role {
475             my $self = shift;
476             if (@_) {
477             $self->{DOCUMENT}->{type} = shift;
478             }
479             return $self->{DOCUMENT}->{type};
480             }
481              
482             sub type {
483             role( @_ );
484             }
485              
486             sub determine_type {
487             role( @_ );
488             }
489              
490             =item B
491              
492             Return, or set, the version of the RTML specification used
493              
494             my $version = $object->version();
495             $object->version( $version );
496              
497             =cut
498              
499             sub version {
500             my $self = shift;
501             if (@_) {
502             $self->{DOCUMENT}->{version} = shift;
503             }
504             return $self->{DOCUMENT}->{version};
505             }
506              
507             sub dtd {
508             version( @_ );
509             }
510              
511              
512             # S C H E D U L E #########################################################
513              
514             =back
515              
516             =head2 Scheduling Methods
517              
518             =over 4
519              
520             =item B
521              
522             Return, or set, the group count of the observation
523              
524             my $num = $object->group_count();
525             $object->group_count( $num );
526            
527             =cut
528              
529             sub group_count {
530             my $self = shift;
531             if (@_) {
532             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{Count} = shift;
533             }
534             return $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{Count};
535             }
536              
537             sub groupcount {
538             group_count( @_ );
539             }
540              
541             =item B
542              
543             Return, or set, the exposure time of the observation
544              
545             my $num = $object->exposure_time();
546             $object->exposure_time( $num );
547            
548             =cut
549              
550             sub exposure_time {
551             my $self = shift;
552             if (@_) {
553             my $exposure = shift;
554             if ( defined $self->exposure_units() && $self->exposure_units() eq "ms" ) {
555             $exposure = $exposure / 1000.0;
556             }
557             $exposure =~ s/^\s*//;
558             $exposure =~ s/\s*$//;
559             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{content} = $exposure;
560             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{type} = "time";
561             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{units} = "seconds";
562             }
563             my $exposure = $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{content};
564             if ( defined $exposure ) {
565             $exposure =~ s/^\s*//;
566             $exposure =~ s/\s*$//;
567             if ( $self->exposure_units() eq "ms" ) {
568             $exposure = $exposure / 1000.0;
569             $self->exposure_units( "seconds" );
570             }
571             }
572             return $exposure;
573             }
574              
575             sub exposuretime {
576             exposure_time( @_ );
577             }
578              
579             sub exposure {
580             exposure_time( @_ );
581             }
582              
583             =item B
584              
585             Return, or set, the S/N of the observation
586              
587             my $num = $object->signal_to_noise();
588             $object->signal_to_noise( $num );
589            
590             =cut
591              
592             sub signal_to_noise {
593             my $self = shift;
594             if (@_) {
595             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{content} = shift;
596             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{type} = "snr";
597             }
598             return $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{content};
599             }
600              
601             sub signaltonoise {
602             signal_to_noise( @_ );
603             }
604              
605             sub snr {
606             signal_to_noise( @_ );
607             }
608              
609             =item B
610              
611             Sets (or returns) the flux of the object needed for signal to noise
612             calculations for the image
613              
614             my $mag = $object->reference_flux();
615             $object->reference_flux( $mag );
616              
617             the flux should be a continuum R band magnitude value.
618            
619             =cut
620              
621             sub reference_flux {
622             my $self = shift;
623             if (@_) {
624             $self->{DOCUMENT}->{Observation}->{Target}->{Flux}->{content} = shift;
625             }
626             return $self->{DOCUMENT}->{Observation}->{Target}->{Flux}->{content};
627             }
628              
629             sub flux {
630             reference_flux( @_ );
631             }
632              
633             =item B
634              
635             Return, or set, the type of exposure of the observation
636              
637             my $string = $object->exposure_type();
638             $object->exposure_type( $string );
639              
640             where $string can have values of "snr" or "time".
641            
642             =cut
643              
644             sub exposure_type {
645             my $self = shift;
646             if (@_) {
647             my $type = shift;
648             if ( $type eq "snr" ) {
649             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{type} = "snr";
650             } else {
651             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{type} = "time";
652             $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{units} = "seconds";
653             }
654             }
655             return $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{type};
656             }
657              
658             sub exposuretype {
659             exposure_type( @_ );
660             }
661              
662             sub exposure_units {
663             my $self = shift;
664             return $self->{DOCUMENT}->{Observation}->{Schedule}->{Exposure}->{units};
665             }
666              
667             sub exposureunits {
668             exposure_units( @_ );
669             }
670              
671             =item B
672              
673             Return, or set, the series count of the observation
674              
675             my $num = $object->series_count();
676             $object->series_count( $num );
677            
678             =cut
679              
680             sub series_count {
681             my $self = shift;
682             if (@_) {
683             $self->{DOCUMENT}->{Observation}->{Schedule}->{SeriesConstraint}->{Count} = shift;
684             }
685             return $self->{DOCUMENT}->{Observation}->{Schedule}->{SeriesConstraint}->{Count};
686             }
687              
688             sub seriescount {
689             series_count( @_ );
690             }
691              
692             =item B
693              
694             Return, or set, the interval between a series of observations blocks
695              
696             my $num = $object->interval();
697             $object->interval( $num );
698            
699             =cut
700              
701             sub interval {
702             my $self = shift;
703             if (@_) {
704             my $arg = shift;
705             unless ( $arg =~ "PT" ) {
706             $arg = "PT" . $arg;
707             }
708             $self->{DOCUMENT}->{Observation}->{Schedule}->{SeriesConstraint}->{Interval} = $arg;
709             }
710             return $self->{DOCUMENT}->{Observation}->{Schedule}->{SeriesConstraint}->{Interval};
711             }
712              
713             =item B
714              
715             Return, or set, the tolerance between a series of observations blocks
716              
717             my $num = $object->tolerance();
718             $object->tolerance( $num );
719            
720             =cut
721              
722             sub tolerance {
723             my $self = shift;
724             if (@_) {
725             my $arg = shift;
726             unless ( $arg =~ "PT" ) {
727             $arg = "PT" . $arg;
728             }
729             $self->{DOCUMENT}->{Observation}->{Schedule}->{SeriesConstraint}->{Tolerance} = $arg;
730             }
731             return $self->{DOCUMENT}->{Observation}->{Schedule}->{SeriesConstraint}->{Tolerance};
732             }
733              
734              
735             =item B
736              
737             Return, or set, the priority of the observation
738              
739             my $num = $object->priority();
740             $object->priority( $num );
741            
742             Schedule (RTML) priority Phase II Priority Phase II GUI
743             N/A 5 Urgent
744             0 4 (default) Normal
745             1 3 High
746             2 2 Medium
747             3 1 Normal
748             default(other) 1 Normal
749             N/A 0 Normal
750              
751             where: "Schedule (RTML) priority" is the number specified in the RTML:
752             , "Phase II Priority" is the number stored in the
753             Phase II database and "Phase II GUI" is what is displayed in the Phase II GUI.
754              
755             Note:
756             The Phase II priority 4 can be specified by the TEA but cannot be specified
757             by the Phase II GUI (and displays as the default "Normal" in the GUI). The
758             Phase II priority 5 I be specified by the TEA but can be specified by
759             the Phase II GUI as Urgent.
760              
761             =cut
762              
763             sub priority {
764             my $self = shift;
765             if (@_) {
766             $self->{DOCUMENT}->{Observation}->{Schedule}->{priority} = shift;
767             }
768             return $self->{DOCUMENT}->{Observation}->{Schedule}->{priority};
769             }
770              
771             sub schedule_priority {
772             priority( @_ );
773             }
774              
775             =item B
776              
777             Return, or set, the time constraints of the the observation
778              
779             my $array_reference = $object->time_constraint();
780             $object->exposure_type( \@times );
781              
782             where it takes and returns a scalar reference to an array of ISO8601
783             times, e.g. my $array_reference = [ $start, $end ] which maps to,
784              
785            
786             2006-09-10T11:12:51+0100
787             2006-09-12T00:12:51+0100
788            
789            
790             =cut
791              
792             sub time_constraint {
793             my $self = shift;
794              
795             if (@_) {
796            
797             my $ref = shift;
798             my @array = @{$ref};
799            
800             $self->{DOCUMENT}->{Observation}->{Schedule}->{TimeConstraint}->{StartDateTime} = $array[0];
801             $self->{DOCUMENT}->{Observation}->{Schedule}->{TimeConstraint}->{EndDateTime} = $array[1];
802             }
803              
804             return ( $self->{DOCUMENT}->{Observation}->{Schedule}->{TimeConstraint}->{StartDateTime},
805             $self->{DOCUMENT}->{Observation}->{Schedule}->{TimeConstraint}->{EndDateTime} );
806            
807             }
808              
809             sub timeconstraint {
810             time_constraint( @_ );
811             }
812              
813             sub start_time {
814             my $self = shift;
815             return $self->{DOCUMENT}->{Observation}->{Schedule}->{TimeConstraint}->{StartDateTime};
816             }
817              
818             sub end_time{
819             my $self = shift;
820             return $self->{DOCUMENT}->{Observation}->{Schedule}->{TimeConstraint}->{EndDateTime};
821             }
822              
823             # D E V I C E ##############################################################
824              
825             =back
826              
827             =head2 Device Methods
828              
829             =over 4
830              
831             =item B
832              
833             Return, or set, the device type for the observation
834              
835             my $string = $object->device_type();
836             $object->device_type( $string );
837            
838             =cut
839              
840             sub device_type {
841             my $self = shift;
842             if (@_) {
843             $self->{DOCUMENT}->{Observation}->{Device}->{type} = shift;
844             }
845             return $self->{DOCUMENT}->{Observation}->{Device}->{type};
846             }
847              
848             sub devicetype {
849             device_type( @_ );
850             }
851              
852             sub device {
853             device_type( @_ );
854             }
855              
856             =item B
857              
858             Return, or set, the filter type for the observation
859              
860             my $string = $object->filter_type();
861             $object->filter_type( $string );
862            
863             =cut
864              
865             sub filter_type {
866             my $self = shift;
867             if (@_) {
868             $self->{DOCUMENT}->{Observation}->{Device}->{Filter}->{FilterType} = shift;
869             }
870             return $self->{DOCUMENT}->{Observation}->{Device}->{Filter}->{FilterType};
871             }
872              
873             sub filtertype {
874             filter_type( @_ );
875             }
876              
877             sub filter {
878             filter_type( @_ );
879             }
880            
881             # T A R G E T ##############################################################
882              
883             =back
884              
885             =head2 Target Methods
886              
887             =over 4
888              
889             =item B
890              
891             Return, or set, the type of target for the observation
892              
893             my $string = $object->target_type();
894             $object->target_type( $string );
895              
896             there are two types of valid target type; "normal" or "toop". A normal
897             observation is placed into the queue
898            
899             =cut
900              
901             sub target_type {
902             my $self = shift;
903             if (@_) {
904             $self->{DOCUMENT}->{Observation}->{Target}->{type} = shift;
905             }
906             return $self->{DOCUMENT}->{Observation}->{Target}->{type};
907             }
908              
909             sub targettype {
910             target_type( @_ );
911             }
912              
913              
914             =item B
915              
916             Return, or set, the type identifier of target for the observation
917              
918             my $string = $object->target_ident();
919             $object->target_ident( $string );
920              
921             The target identity is used by the eSTAR system to choose post-observation
922             processing blocks, e.g.
923              
924            
925            
926             signifies a normal queued observation which is part of the exo-planet
927             monitoring programme on Robonet-1.0.
928              
929             =cut
930              
931             sub target_ident {
932             my $self = shift;
933             if (@_) {
934             $self->{DOCUMENT}->{Observation}->{Target}->{ident} = shift;
935             }
936             return $self->{DOCUMENT}->{Observation}->{Target}->{ident};
937             }
938              
939             sub targetident {
940             target_ident( @_ );
941             }
942              
943             sub identity {
944             target_ident( @_ );
945             }
946              
947             =item B
948              
949             Return, or set, the target name for the observation
950              
951             my $string = $object->target_name();
952             $object->target_name( $string );
953              
954             =cut
955              
956             sub target_name {
957             my $self = shift;
958             if (@_) {
959             $self->{DOCUMENT}->{Observation}->{Target}->{TargetName} = shift;
960             }
961             return $self->{DOCUMENT}->{Observation}->{Target}->{TargetName};
962             }
963              
964             sub targetname {
965             target_name( @_ );
966             }
967              
968             sub target {
969             target_name( @_ );
970             }
971              
972             =item B
973              
974             Sets (or returns) the type of co-ordinate system expected,
975              
976             my $ra = $object->coordinate_type();
977             $object->coordinate_type( 'equatorial' );
978              
979             defaults to "equatorial". Don't change this unless you know what you're
980             doing and set all the other relevant parameters via the relevant private
981             methods provided by the class.
982              
983             =cut
984              
985             sub coordinate_type {
986             my $self = shift;
987            
988             if (@_) {
989             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{type} = shift;
990             }
991             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{type};
992             }
993              
994             sub coord_type {
995             coordinate_type( @_ );
996             }
997              
998             sub coordinatetype {
999             coordinate_type( @_ );
1000             }
1001              
1002             sub coordtype {
1003             coordinate_type( @_ );
1004             }
1005            
1006             =item B
1007              
1008             Sets (or returns) the target RA
1009              
1010             my $ra = $object->ra();
1011             $object->ra( '12 35 65.0' );
1012              
1013             must be in the form HH MM SS.S.
1014              
1015             =cut
1016              
1017             sub ra {
1018             my $self = shift;
1019              
1020             if (@_) {
1021             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{RightAscension}->{content} = shift;
1022             }
1023             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{RightAscension}->{content};
1024             }
1025            
1026             sub ra_format {
1027             my $self = shift;
1028              
1029             if (@_) {
1030             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{RightAscension}->{format} = shift;
1031             }
1032             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{RightAscension}->{format};
1033             }
1034              
1035             sub raformat {
1036             ra_format( @_ );
1037             }
1038            
1039             sub ra_units {
1040             my $self = shift;
1041              
1042             if (@_) {
1043             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{RightAscension}->{units} = shift;
1044             }
1045             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{RightAscension}->{units};
1046             }
1047              
1048             sub raunits {
1049             ra_units( @_ );
1050             }
1051              
1052             =item B
1053              
1054             Sets (or returns) the target DEC
1055              
1056             my $dec = $object->dec();
1057             $object->dec( '+60 35 32' );
1058              
1059             must be in the form SDD MM SS.S.
1060              
1061             =cut
1062              
1063             sub dec {
1064             my $self = shift;
1065              
1066             if (@_) {
1067             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Declination}->{content} = shift;
1068             }
1069             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Declination}->{content};
1070             }
1071            
1072             sub dec_format {
1073             my $self = shift;
1074              
1075             if (@_) {
1076             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Declination}->{format} = shift;
1077             }
1078             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Declination}->{format};
1079             }
1080              
1081             sub decformat {
1082             dec_format( @_ );
1083             }
1084            
1085             sub dec_units {
1086             my $self = shift;
1087              
1088             if (@_) {
1089             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Declination}->{units} = shift;
1090             }
1091             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Declination}->{units};
1092             }
1093              
1094             sub decunits {
1095             dec_units( @_ );
1096             }
1097              
1098             =item B
1099              
1100             Sets (or returns) the equinox of the target co-ordinates
1101              
1102             my $equnox = $object->equinox();
1103             $object->equinox( 'B1950' );
1104              
1105             default is J2000, currently the telescope expects J2000.0 coordinates, no
1106             translation is currently carried out by the library before formatting the
1107             RTML message. It is therefore suggested that the user provides their
1108             coordinates in J2000.0 as this is merely a placeholder routine.
1109              
1110             =cut
1111              
1112             sub equinox {
1113             my $self = shift;
1114              
1115             if (@_) {
1116             $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Equinox} = shift;
1117             }
1118             return $self->{DOCUMENT}->{Observation}->{Target}->{Coordinates}->{Equinox};
1119             }
1120              
1121            
1122             # A G E N T ##############################################################
1123              
1124             =back
1125              
1126             =head2 Agent Methods
1127              
1128             =over 4
1129              
1130             =item B
1131              
1132             Return, or set, the host to return asynchronous messages to regarding the
1133             status of the observation, see also C.
1134              
1135             my $string = $object->host();
1136             $object->host( $string );
1137              
1138             defaults to the current machine's IP address
1139            
1140             =cut
1141              
1142             sub host {
1143             my $self = shift;
1144             if (@_) {
1145             $self->{DOCUMENT}->{IntelligentAgent}->{host} = shift;
1146             }
1147             return $self->{DOCUMENT}->{IntelligentAgent}->{host};
1148             }
1149              
1150             sub host_name {
1151             host( @_ );
1152             }
1153              
1154             sub agent_host {
1155             host( @_ );
1156             }
1157              
1158             =item B
1159              
1160             Return, or set, the port to return asynchronous messages to regarding the
1161             status of the observation, see also C.
1162              
1163             my $string = $object->port();
1164             $object->port( $string );
1165              
1166             defaults to 8000.
1167            
1168             =cut
1169              
1170             sub port {
1171             my $self = shift;
1172             if (@_) {
1173             $self->{DOCUMENT}->{IntelligentAgent}->{port} = shift;
1174             }
1175             return $self->{DOCUMENT}->{IntelligentAgent}->{port};
1176             }
1177              
1178             sub port_number {
1179             port( @_ );
1180             }
1181              
1182             sub portnumber {
1183             port( @_ );
1184             }
1185              
1186             =item B
1187              
1188             Sets (or returns) the unique ID for the observation request
1189              
1190             my $id = $object->id();
1191             $object->id( 'IATEST0001:CT1:0013' );
1192              
1193             note that there is NO DEFAULT, a unique ID for the score/observing
1194             request must be supplied, see the eSTAR Communications and the TEA
1195             command set documents for further details.
1196              
1197             Note: This is I the same thing as the I for the
1198             observation.
1199              
1200             =cut
1201              
1202             sub id {
1203             my $self = shift;
1204              
1205             if (@_) {
1206             $self->{DOCUMENT}->{IntelligentAgent}->{content} = shift;
1207             }
1208              
1209             # return the current ID
1210             return $self->{DOCUMENT}->{IntelligentAgent}->{content};
1211             }
1212            
1213             sub unique_id {
1214             id( @_ );
1215             }
1216            
1217             sub uniqueid {
1218             id( @_ );
1219             }
1220            
1221             # C O N A C T ##############################################################
1222              
1223             =back
1224              
1225             =head2 Contact Methods
1226              
1227             =over 4
1228              
1229             =item B
1230              
1231             Return, or set, the name of the observer
1232              
1233             my $string = $object->name();
1234             $object->name( $string );
1235              
1236            
1237             =cut
1238              
1239             sub name {
1240             my $self = shift;
1241             if (@_) {
1242             $self->{DOCUMENT}->{Contact}->{Name} = shift;
1243             }
1244             return $self->{DOCUMENT}->{Contact}->{Name};
1245             }
1246              
1247             sub observer_name {
1248             name( @_ );
1249             }
1250              
1251             sub real_name {
1252             name( @_ );
1253             }
1254              
1255              
1256             sub observername {
1257             name( @_ );
1258             }
1259              
1260             sub realname {
1261             name( @_ );
1262             }
1263              
1264             =item B
1265              
1266             Return, or set, the user name of the observer
1267              
1268             my $string = $object->user();
1269             $object->user( $string );
1270              
1271             e.g. PATT/keith.horne
1272            
1273             =cut
1274              
1275             sub user {
1276             my $self = shift;
1277             if (@_) {
1278             $self->{DOCUMENT}->{Contact}->{User} = shift;
1279             }
1280             return $self->{DOCUMENT}->{Contact}->{User};
1281             }
1282              
1283             sub user_name {
1284             user( @_ );
1285             }
1286              
1287             sub username {
1288             user( @_ );
1289             }
1290              
1291             =item B
1292              
1293             Return, or set, the institutional affliation of the observer
1294              
1295             my $string = $object->institution();
1296             $object->institution( $string );
1297              
1298             e.g. University of Exeter
1299            
1300             =cut
1301              
1302             sub institution {
1303             my $self = shift;
1304             if (@_) {
1305             $self->{DOCUMENT}->{Contact}->{Institution} = shift;
1306             }
1307             return $self->{DOCUMENT}->{Contact}->{Institution};
1308             }
1309              
1310             sub institution_affiliation {
1311             institution( @_ );
1312             }
1313              
1314             =item B
1315              
1316             Return, or set, the email address of the observer
1317              
1318             my $string = $object->email();
1319             $object->email( $string );
1320            
1321             =cut
1322              
1323             sub email {
1324             my $self = shift;
1325             if (@_) {
1326             $self->{DOCUMENT}->{Contact}->{Email} = shift;
1327             }
1328             return $self->{DOCUMENT}->{Contact}->{Email};
1329             }
1330              
1331             sub email_address {
1332             email( @_ );
1333             }
1334              
1335             sub emailddress {
1336             email( @_ );
1337             }
1338              
1339             =item B
1340              
1341             Return, or set, the user name of the observer
1342              
1343             my $string = $object->user();
1344             $object->user( $string );
1345              
1346             e.g. PATT/keith.horne
1347            
1348             =cut
1349              
1350             sub project {
1351             my $self = shift;
1352             if (@_) {
1353             $self->{DOCUMENT}->{Project} = shift;
1354             }
1355             my $project = $self->{DOCUMENT}->{Project};
1356             return $project unless defined reftype($project);
1357             $project = undef if reftype($project) eq "HASH"; # hash implies an empty tag
1358             return $project;
1359             }
1360              
1361            
1362             # S C O R I N G ##############################################################
1363              
1364             =back
1365              
1366             =head2 Scoring Methods
1367              
1368             =over 4
1369              
1370             =item B
1371              
1372             Sets (or returns) the target score
1373              
1374             my $score = $object->score();
1375             $object->score( $score );
1376              
1377             the score will be between 0.0 and 1.0
1378              
1379             =cut
1380              
1381             sub score {
1382             my $self = shift;
1383              
1384             if (@_) {
1385             $self->{DOCUMENT}->{Score} = shift;
1386             }
1387              
1388             # return the current target score
1389             return $self->{DOCUMENT}->{Score};
1390             }
1391              
1392            
1393             =item B
1394              
1395             Sets (or returns) the target completion time
1396              
1397             my $time = $object->completion_time();
1398             $object->completion_time( $time );
1399              
1400             the completion time should be of the format YYYY-MM-DDTHH:MM:SS
1401              
1402             =cut
1403              
1404             sub completion_time {
1405             my $self = shift;
1406              
1407             if (@_) {
1408             $self->{DOCUMENT}->{CompletionTime} = shift;
1409             }
1410              
1411             # return the current target score
1412             return $self->{DOCUMENT}->{CompletionTime};
1413             }
1414              
1415             sub completiontime {
1416             completion_time( @_ );
1417             }
1418              
1419             sub time {
1420             completion_time( @_ );
1421             }
1422              
1423            
1424             # D A T A ################################################################
1425              
1426             =back
1427              
1428             =head2 Data Methods
1429              
1430             =over 4
1431              
1432             =item B
1433              
1434             Sets (or returns) the data associated with the observation
1435              
1436             my @data = $object->data( );
1437             $object->data( @data );
1438              
1439             Takes an array of hashes where,
1440              
1441             @data = [ { Catalogue => ' ', Header => ' ', URL => ' ' },
1442             { Catalogue => ' ', Header => ' ', URL => ' ' },
1443             .
1444             .
1445             .
1446             { Catalogue => ' ', Header => ' ', URL => ' ' } ];
1447              
1448             and the value of the Catalogue hash entry is a URL pointing to a VOTavle,
1449             the Header hash entry is a FITS header block and the URL is either points
1450             to a FITS file, or other associated data product. You can I append
1451             data to an existing memory structure, any data passed via this routine
1452             will overwrite any existing data structure in memory.
1453              
1454             The routine returns a similar array when queried. This array will be
1455             populated either by calling C, or through parsing a document.
1456              
1457             =cut
1458              
1459             sub data {
1460             my $self = shift;
1461              
1462             # TAKING DATA INTO THE MESSAGE
1463             if (@_) {
1464             my @array = @_;
1465             $self->{DOCUMENT}->{Observation}->{ImageData} = [];
1466             foreach my $i ( 0 ... $#array ) {
1467             my %hash = %{$array[$i]};
1468              
1469             # Images
1470             if ( defined $hash{URL} ) {
1471             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{content} = $hash{URL};
1472             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{delivery} = "url";
1473             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{type} = "FITS16";
1474             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{reduced} = "true";
1475             }
1476            
1477             # Catalogues
1478             if( defined $hash{Catalogue} ) {
1479             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{ObjectList}->{content} = $hash{Catalogue};
1480             if( $hash{Catalogue} =~ "http" && $hash{Catalogue} =~ "votable" ) {
1481             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{ObjectList}->{type} = "votable-url";
1482             } else {
1483             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{ObjectList}->{type} = "unknown";
1484             }
1485             }
1486            
1487             # FITS Headers
1488             if( defined $hash{Catalogue} ) {
1489             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{FITSHeader}->{content} = $hash{Header};
1490             $self->{DOCUMENT}->{Observation}->{ImageData}[$i]->{FITSHeader}->{type} = "all";
1491             }
1492            
1493             } # end of foreach loop
1494             } # end of if ( @_ ) block
1495              
1496             # PUSHING DATA OUT OF THE MESSAGE
1497             if ( defined $self->{DOCUMENT}->{Observation}->{ImageData} &&
1498             reftype($self->{DOCUMENT}->{Observation}->{ImageData}) eq "HASH" ) {
1499             return ();
1500             }
1501             my @output;
1502            
1503             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1504             my $header = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{FITSHeader}->{content};
1505             my $url = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{content};
1506             my $catalogue = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{ObjectList}->{content};
1507             if ( defined $url ) {
1508             $url =~ s/^\s*//;
1509             $url =~ s/\s*$//;
1510            
1511             }
1512             if ( defined $catalogue ) {
1513             $catalogue =~ s/^\s*//;
1514             $catalogue =~ s/\s*$//;
1515             }
1516             $output[$j] = ( { Catalogue => $catalogue,
1517             URL => $url,
1518             Header => $header } );
1519             }
1520             return @output;
1521             }
1522              
1523             sub headers {
1524             my $self = shift;
1525            
1526             if ( defined $self->{DOCUMENT}->{Observation}->{ImageData} &&
1527             reftype($self->{DOCUMENT}->{Observation}->{ImageData}) eq "HASH" ) {
1528             return ();
1529             }
1530             my @output;
1531             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1532             my $header = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{FITSHeader}->{content};
1533             $output[$j] = $header;
1534             }
1535             return @output;
1536             }
1537              
1538             sub images {
1539             my $self = shift;
1540              
1541             if ( defined $self->{DOCUMENT}->{Observation}->{ImageData} &&
1542             reftype($self->{DOCUMENT}->{Observation}->{ImageData}) eq "HASH" ) {
1543             return ();
1544             }
1545             my @output;
1546             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1547             my $url = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{content};
1548             if ( defined $url ) {
1549             $url =~ s/^\s*//;
1550             $url =~ s/\s*$//;
1551             }
1552             $output[$j] = $url;
1553             }
1554             return @output;
1555             }
1556              
1557             sub catalogues {
1558             my $self = shift;
1559            
1560             if ( defined $self->{DOCUMENT}->{Observation}->{ImageData} &&
1561             reftype($self->{DOCUMENT}->{Observation}->{ImageData}) eq "HASH" ) {
1562             return ();
1563             }
1564             my @output;
1565             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1566             my $catalogue = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{ObjectList}->{content};
1567             if ( defined $catalogue ) {
1568             $catalogue =~ s/^\s*//;
1569             $catalogue =~ s/\s*$//;
1570             }
1571             $output[$j] = $catalogue;
1572             }
1573             return @output;
1574             }
1575              
1576             sub image_delivery {
1577             my $self = shift;
1578              
1579             my @output;
1580             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1581             my $delivery = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{delivery};
1582             $output[$j] = $delivery;
1583             }
1584             return @output;
1585             }
1586              
1587             sub image_type {
1588             my $self = shift;
1589              
1590             my @output;
1591             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1592             my $type = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{type};
1593             $output[$j] = $type;
1594             }
1595             return @output;
1596             }
1597            
1598             sub image_reduced {
1599             my $self = shift;
1600              
1601             my @output;
1602             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1603             my $reduced = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{reduced};
1604             $output[$j] = $reduced;
1605             }
1606             return @output;
1607             }
1608              
1609             sub catalogue_type {
1610             my $self = shift;
1611              
1612             my @output;
1613             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1614             my $type = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{ObjectList}->{type};
1615             $output[$j] = $type;
1616             }
1617             return @output;
1618             }
1619              
1620             sub header_type {
1621             my $self = shift;
1622              
1623             my @output;
1624             foreach my $j ( 0 .. $#{$self->{DOCUMENT}->{Observation}->{ImageData}} ) {
1625             my $type = $self->{DOCUMENT}->{Observation}->{ImageData}[$j]->{FITSHeader}->{type};
1626             $output[$j] = $type;
1627             }
1628             return @output;
1629             }
1630            
1631             # G E N E R A L ------------------------------------------------------------
1632              
1633             =back
1634              
1635             =head2 General Methods
1636              
1637             =over 4
1638              
1639             =item B
1640              
1641             Dumps the contents of the RTML buffer in memory to a scalar,
1642              
1643             my $object = new XML::Document::RTML();
1644             $object->build( %hash );
1645             my $document = $object->dump_buffer();
1646              
1647             If C has not been called this function will return an undef.
1648              
1649             =cut
1650              
1651             sub dump_buffer {
1652             my $self = shift;
1653            
1654             if ( defined $self->{BUFFER} ){
1655             return $self->{BUFFER}->value();
1656             } else {
1657             return undef;
1658             }
1659             }
1660              
1661             sub dump_rtml {
1662             dump_buffer( @_ );
1663             }
1664              
1665             sub buffer {
1666             dump_buffer( @_ );
1667             }
1668              
1669             =item B
1670              
1671             Returns a refence to the parsed RTML document hash currently held in memory,
1672              
1673             my $object = new XML::Document::RTML( XML => $xml );
1674             my $hash_reference = $object->dump_tree();
1675              
1676             should return an undefined value if that tree is empty. This error will occur
1677             if we haven't called C to create a document, or populated the tree using
1678             the object creator by calling the XML or File methods to read in a document.
1679              
1680             =cut
1681              
1682             sub dump_tree {
1683             my $self = shift;
1684            
1685             if ( defined $self->{DOCUMENT} ){
1686             return $self->{DOCUMENT};
1687             } else {
1688             return undef;
1689             }
1690             }
1691              
1692             sub dump_hash {
1693             dump_tree( @_ );
1694             }
1695              
1696             sub tree {
1697             dump_tree( @_ );
1698             }
1699              
1700              
1701             # C O N F I G U R E ---------------------------------------------------------
1702              
1703             =item B
1704              
1705             Configures the object, takes an options hash as an argument
1706              
1707             $message->configure( %options );
1708              
1709             Does nothing if the hash is not supplied. This is called directly from
1710             the constructor during object creation
1711              
1712             =cut
1713              
1714              
1715             sub configure {
1716             my $self = shift;
1717              
1718             # BLESS XML WRITER
1719             # ----------------
1720             $self->{BUFFER} = new XML::Writer::String();
1721             $self->{WRITER} = new XML::Writer( OUTPUT => $self->{BUFFER},
1722             DATA_MODE => 1,
1723             UNSAFE => 1,
1724             DATA_INDENT => 4 );
1725            
1726             # DEFAULTS
1727             # --------
1728            
1729             # use the RTML Namespace as defined by the v2.2 DTD by default
1730             $self->version( 2.2 );
1731             $self->{DTD} = "http://www.estar.org.uk/documents/rtml" . $self->version() . ".dtd";
1732            
1733             # we're guessing we're talking to
1734             $self->host( "127.0.0.1" );
1735             $self->port( 8000 );
1736            
1737             # default to J2000
1738             $self->coordinate_type( "equatorial" );
1739             $self->equinox ( "J2000" );
1740             $self->raformat( "hh mm ss.ss" );
1741             $self->raunits( "hms" );
1742             $self->decformat( "dd mm ss.ss" );
1743             $self->decunits( "dms" );
1744            
1745             # default to using the queue with "normal" priority
1746             $self->priority( 3 );
1747             $self->target_type( "normal" );
1748             $self->target_ident( "SingleExposure" );
1749             $self->exposure_type( "time" );
1750            
1751             # default to a CCD camera, and an R-band filter
1752             $self->device_type( "camera" );
1753             $self->filter_type( "R" );
1754              
1755             # CONFIGURE FROM ARGUEMENTS
1756             # -------------------------
1757              
1758             # return unless we have arguments
1759             return undef unless @_;
1760              
1761             # grab the argument list
1762             my %args = @_;
1763            
1764             # Loop over the keys that mean we're parsing a document
1765             for my $key (qw / File XML / ) {
1766             if ( lc($key) eq "file" && exists $args{$key} ) {
1767             eval { $self->_parse( File => $args{$key} ); };
1768             if ( $@ ) {
1769             die "$@";
1770             }
1771             last;
1772            
1773             } elsif ( lc($key) eq "xml" && exists $args{$key} ) {
1774             eval { $self->_parse( XML => $args{$key} ); };
1775             if ( $@ ) {
1776             die "$@";
1777             }
1778             last;
1779            
1780             }
1781             }
1782            
1783             # Loop over the rest of the keys
1784             for my $other (qw / Role Type Version DTD GroupCount ExposureTime Exposure
1785             SignalToNoise Snr Flux ExposureType ExposureUnits
1786             SeriesCount Interval Tolerance Priority TimeConstraint
1787             DeviceType Device FilterType Filter TargetType TargetIdent
1788             Identity TargetName Target CoordinateType Coordtype
1789             RA RAFormat RAUnits Dec DecFormat DecUnits Equinox
1790             Host Port PortNumber ID UniqueID Name ObserverName
1791             RealName User UserName Institution Email EmailAddress
1792             Project Score CompletionTime Time Data / ) {
1793             my $method = lc($other);
1794             $self->$method( $args{$other} ) if exists $args{$other};
1795             }
1796            
1797             # Nothing to configure...
1798             return undef;
1799              
1800             }
1801              
1802              
1803             # P R I V A T E M E T H O D S ------------------------------------------
1804              
1805             sub _parse {
1806             my $self = shift;
1807              
1808             # return unless we have arguments
1809             return undef unless @_;
1810              
1811             # grab the argument list
1812             my %args = @_;
1813              
1814             my $xs = new XML::Simple( );
1815              
1816             # Loop over the allowed keys
1817             for my $key (qw / File XML / ) {
1818             if ( lc($key) eq "file" && exists $args{$key} ) {
1819             $args{$key} =~ s/US_ASCII/ISO-8859-1/;
1820             $self->{DOCUMENT} = $xs->XMLin( $args{$key}, ForceArray => [ "ImageData" ] );
1821             last;
1822            
1823             } elsif ( lc($key) eq "xml" && exists $args{$key} ) {
1824             $args{$key} =~ s/US_ASCII/ISO-8859-1/;
1825             $self->{DOCUMENT} = $xs->XMLin( $args{$key}, ForceArray => [ "ImageData" ] );
1826             last;
1827            
1828             }
1829             }
1830            
1831             #print Dumper( $self->{DOCUMENT} );
1832             return;
1833             }
1834              
1835             # L A S T O R D E R S ------------------------------------------------------
1836              
1837             1;