File Coverage

lib/Geo/EOP.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             # Copyrights 2008-2015 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.01.
5 3     3   50728 use warnings;
  3         8  
  3         145  
6 3     3   19 use strict;
  3         5  
  3         137  
7              
8             package Geo::EOP;
9 3     3   39 use vars '$VERSION';
  3         11  
  3         247  
10             $VERSION = '0.50';
11              
12 3     3   46 use base 'Geo::GML';
  3         5  
  3         2179  
13              
14             use Geo::EOP::Util; # all
15             use Geo::GML::Util qw/:gml311/;
16              
17             use Log::Report 'geo-eop', syntax => 'SHORT';
18             use XML::Compile::Util qw/unpack_type pack_type type_of_node/;
19             use Math::Trig qw/rad2deg deg2rad/;
20              
21             # map namespace always to the newest implementation of the protocol
22             my %ns2version =
23             ( &NS_HMA_ESA => '1.0'
24             , &NS_EOP_ESA => '1.2.1'
25             );
26              
27             # list all available versions
28             # It is a pity that not all schema use the same prefixes... sometimes,
29             # the dafault prefix is used... therefore, we have to configure all that
30             # manually.
31              
32             my @stdprefs = # will be different in the future
33             ( sar => NS_SAR_ESA
34             , atm => NS_ATM_ESA
35             , gml => NS_GML_311
36             );
37              
38             my %info =
39             ( '1.0' =>
40             { prefixes => {hma => NS_HMA_ESA, ohr => NS_OHR_ESA, @stdprefs}
41             , eop_schemas => [ 'hma1.0/{eop,sar,opt,atm}.xsd' ]
42             , gml_schemas => [ 'eop1.1/gmlSubset.xsd' ]
43             , gml_version => '3.1.1eop'
44             }
45              
46             , '1.1' =>
47             { prefixes => {eop => NS_EOP_ESA, opt => NS_OPT_ESA, @stdprefs}
48             , eop_schemas => [ 'eop1.1/{eop,sar,opt,atm}.xsd' ]
49             , gml_schemas => [ 'eop1.1/gmlSubset.xsd' ]
50             , gml_version => '3.1.1eop'
51             }
52              
53             , '1.2beta' =>
54             { prefixes => {eop => NS_EOP_ESA, opt => NS_OPT_ESA, @stdprefs}
55             , eop_schemas => [ 'eop1.2beta/{eop,sar,opt,atm}.xsd' ]
56             , gml_schemas => [ 'eop1.1/gmlSubset.xsd' ]
57             , gml_version => '3.1.1eop'
58             }
59              
60             , '1.2.1' =>
61             { prefixes => {eop => NS_EOP_ESA, opt => NS_OPT_ESA, @stdprefs}
62             , eop_schemas => [ 'eop1.2.1/{eop,sar,opt,atm}.xsd' ]
63             , gml_schemas => [ 'eop1.2.1/gmlSubset.xsd' ]
64             , gml_version => '3.1.1eop'
65             }
66              
67             # , '2.0' =>
68             # { eop_schemas => [ 'eop2.0/*.xsd' ]
69             # , gml_version => '3.2.1'
70             # }
71              
72             );
73              
74             my %measure =
75             ( rad_deg => sub { rad2deg $_[0] }
76             , deg_rad => sub { deg2rad $_[0] }
77             , '%_float' => sub { $_[0] / 100 }
78             , 'float_%' => sub { sprintf "%.2f", $_[0] / 100 }
79             );
80             sub _convert_measure($@);
81              
82             # This list must be extended, but I do not know what people need.
83             my @declare_always = ();
84              
85              
86             sub new($@) { my $class = shift; $class->SUPER::new('RW', @_) }
87              
88             sub init($)
89             { my ($self, $args) = @_;
90             $args->{allow_undeclared} = 1
91             unless exists $args->{allow_undeclared};
92              
93             my $version = $args->{eop_version}
94             or error __x"EOP object requires an explicit eop_version";
95              
96             unless(exists $info{$version})
97             { exists $ns2version{$version}
98             or error __x"EOP version {v} not recognized", v => $version;
99             $version = $ns2version{$version};
100             }
101             $self->{GE_version} = $version;
102             my $info = $info{$version};
103              
104             $args->{version} = $info->{gml_version};
105             if($info->{gml_schemas}) # using own GML 3.1.1 subset
106             { $self->_register_gml_version($info->{gml_version} => {});
107             }
108              
109             $self->SUPER::init($args);
110              
111             $self->addPrefixes($info->{prefixes});
112              
113             (my $xsd = __FILE__) =~ s!\.pm!/xsd!;
114             my @xsds = map {glob "$xsd/$_"}
115             @{$info->{eop_schemas} || []}, @{$info->{gml_schemas} || []};
116              
117             $self->importDefinitions(\@xsds);
118              
119             my $units = delete $args->{units};
120             if($units)
121             { if(my $a = $units->{angle})
122             { $self->addHook(type => 'gml:AngleType'
123             , after => sub { _convert_measure $a, @_} );
124             }
125             if(my $d = $units->{distance})
126             { $self->addHook(type => 'gml:MeasureType'
127             , after => sub { _convert_measure $d, @_} );
128             }
129             if(my $p = $units->{percentage})
130             { $self->addHook(path => qr/Percentage/
131             , after => sub { _convert_measure $p, @_} );
132             }
133             }
134              
135             $self;
136             }
137              
138             sub declare(@)
139             { my $self = shift;
140              
141             my $direction = $self->direction;
142              
143             $self->declare($direction, $_)
144             for @_, @declare_always;
145              
146             $self;
147             }
148              
149              
150             sub from($@)
151             { my ($thing, $data, %args) = @_;
152             my $xml = XML::Compile->dataToXML($data);
153              
154             my $product = type_of_node $xml;
155             my $version = $xml->getAttribute('version');
156             defined $version
157             or error __x"no version attribute in root element";
158              
159             my $self;
160             if(ref $thing) # instance method
161             { $self = $thing;
162             }
163             else # class method
164             { exists $info{$version}
165             or error __x"EOP version {version} not (yet) supported. Upgrade Geo::EOP or inform author"
166             , version => $version;
167              
168             $self = $thing->new(eop_version => $version);
169             }
170              
171             my $r = $self->reader($product, %args);
172             defined $r
173             or error __x"do not understand root node {type}", type => $product;
174              
175             ($product, $r->($xml));
176             }
177              
178             #---------------------------------
179              
180              
181             sub eopVersion() {shift->{GE_version}}
182              
183             #--------------
184              
185              
186             sub printIndex(@)
187             { my $self = shift;
188             my $fh = @_ % 2 ? shift : select;
189             $self->SUPER::printIndex($fh
190             , kinds => 'element', list_abstract => 0, @_);
191             }
192              
193             # This code will probaby move to Geo::GML
194             sub _convert_measure($@) # not $$$$ for right context
195             { my ($to, $node, $data, $path) = @_;
196             ref $data eq 'HASH' or return $data;
197             my ($val, $from) = @$data{'_', 'uom'};
198             defined $val && $from or return $data;
199              
200             return $val if $from eq $to;
201             my $code = $measure{$from.'_'.$to} or return $data;
202             $code->($val);
203             }
204              
205             #----------------------
206              
207              
208             1;