/usr/local/CPAN/Geo-EOP/Geo/EOP.pm
# Copyrights 2008-2009 by Mark Overmeer.
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 1.06.
use warnings;
use strict;
package Geo::EOP;
use vars '$VERSION';
$VERSION = '0.13';
use base 'Geo::GML';
use Geo::EOP::Util; # all
use Geo::GML::Util qw/:gml311/;
use Log::Report 'geo-eop', syntax => 'SHORT';
use XML::Compile::Util qw/unpack_type pack_type type_of_node/;
use Math::Trig qw/rad2deg deg2rad/;
# map namespace always to the newest implementation of the protocol
my %ns2version =
( &NS_HMA_ESA => '1.0'
, &NS_EOP_ESA => '1.2.1'
);
# list all available versions
# It is a pity that not all schema use the same prefixes... sometimes,
# the dafault prefix is used... therefore, we have to configure all that
# manually.
my @stdprefs = # will be different in the future
( sar => NS_SAR_ESA
, atm => NS_ATM_ESA
, gml => NS_GML_311
);
my %info =
( '1.0' =>
{ prefixes => {hma => NS_HMA_ESA, ohr => NS_OHR_ESA, @stdprefs}
, eop_schemas => [ 'hma1.0/{eop,sar,opt,atm}.xsd' ]
, gml_schemas => [ 'eop1.1/gmlSubset.xsd' ]
, gml_version => '3.1.1eop'
}
, '1.1' =>
{ prefixes => {eop => NS_EOP_ESA, opt => NS_OPT_ESA, @stdprefs}
, eop_schemas => [ 'eop1.1/{eop,sar,opt,atm}.xsd' ]
, gml_schemas => [ 'eop1.1/gmlSubset.xsd' ]
, gml_version => '3.1.1eop'
}
, '1.2beta' =>
{ prefixes => {eop => NS_EOP_ESA, opt => NS_OPT_ESA, @stdprefs}
, eop_schemas => [ 'eop1.2beta/{eop,sar,opt,atm}.xsd' ]
, gml_schemas => [ 'eop1.1/gmlSubset.xsd' ]
, gml_version => '3.1.1eop'
}
, '1.2.1' =>
{ prefixes => {eop => NS_EOP_ESA, opt => NS_OPT_ESA, @stdprefs}
, eop_schemas => [ 'eop1.2.1/{eop,sar,opt,atm}.xsd' ]
, gml_schemas => [ 'eop1.2.1/gmlSubset.xsd' ]
, gml_version => '3.1.1eop'
}
# , '2.0' =>
# { eop_schemas => [ 'eop2.0/*.xsd' ]
# , gml_version => '3.2.1'
# }
);
my %measure =
( rad_deg => sub { rad2deg $_[0] }
, deg_rad => sub { deg2rad $_[0] }
, '%_float' => sub { $_[0] / 100 }
, 'float_%' => sub { sprintf "%.2f", $_[0] / 100 }
);
sub _convert_measure($@);
# This list must be extended, but I do not know what people need.
my @declare_always = ();
sub new($@) { my $class = shift; $class->SUPER::new('RW', @_) }
sub init($)
{ my ($self, $args) = @_;
$args->{allow_undeclared} = 1
unless exists $args->{allow_undeclared};
my $version = $args->{eop_version}
or error __x"EOP object requires an explicit eop_version";
unless(exists $info{$version})
{ exists $ns2version{$version}
or error __x"EOP version {v} not recognized", v => $version;
$version = $ns2version{$version};
}
$self->{GE_version} = $version;
my $info = $info{$version};
$args->{version} = $info->{gml_version};
if($info->{gml_schemas}) # using own GML 3.1.1 subset
{ $self->_register_gml_version($info->{gml_version} => {});
}
$self->SUPER::init($args);
$self->prefixes($info->{prefixes});
(my $xsd = __FILE__) =~ s!\.pm!/xsd!;
my @xsds = map {glob "$xsd/$_"}
@{$info->{eop_schemas} || []}, @{$info->{gml_schemas} || []};
$self->importDefinitions(\@xsds);
my $units = delete $args->{units};
if($units)
{ if(my $a = $units->{angle})
{ $self->addHook(type => 'gml:AngleType'
, after => sub { _convert_measure $a, @_} );
}
if(my $d = $units->{distance})
{ $self->addHook(type => 'gml:MeasureType'
, after => sub { _convert_measure $d, @_} );
}
if(my $p = $units->{percentage})
{ $self->addHook(path => qr/Percentage/
, after => sub { _convert_measure $p, @_} );
}
}
$self;
}
sub declare(@)
{ my $self = shift;
my $direction = $self->direction;
$self->declare($direction, $_)
for @_, @declare_always;
$self;
}
sub from($@)
{ my ($class, $data, %args) = @_;
my $xml = XML::Compile->dataToXML($data);
my $product = type_of_node $xml;
my $version = $xml->getAttribute('version');
defined $version
or error __x"no version attribute in root element";
exists $info{$version}
or error __x"EOP version {version} not (yet) supported. Upgrade Geo::EOP or inform author"
, version => $version;
my $self = $class->new(eop_version => $version, %args);
my $r = $self->reader($product);
defined $r
or error __x"do not understand root node {type}", type => $product;
($product, $r->($xml));
}
#---------------------------------
sub eopVersion() {shift->{GE_version}}
#--------------
sub printIndex(@)
{ my $self = shift;
my $fh = @_ % 2 ? shift : select;
$self->SUPER::printIndex($fh
, kinds => 'element', list_abstract => 0, @_);
}
# This code will probaby move to Geo::GML
sub _convert_measure($@) # not $$$$ for right context
{ my ($to, $node, $data, $path) = @_;
ref $data eq 'HASH' or return $data;
my ($val, $from) = @$data{'_', 'uom'};
defined $val && $from or return $data;
return $val if $from eq $to;
my $code = $measure{$from.'_'.$to} or return $data;
$code->($val);
}
#----------------------
1;