File Coverage

lib/Geo/GML.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-2017 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.02.
5 12     12   248889 use warnings;
  12         35  
  12         481  
6 12     12   76 use strict;
  12         28  
  12         486  
7              
8             package Geo::GML;
9 12     12   87 use vars '$VERSION';
  12         37  
  12         842  
10             $VERSION = '0.17';
11              
12 12     12   84 use base 'XML::Compile::Cache';
  12         26  
  12         7237  
13              
14             use Geo::GML::Util;
15              
16             use Log::Report 'geo-gml', syntax => 'SHORT';
17             use XML::Compile::Util qw/unpack_type pack_type type_of_node/;
18             use File::Glob qw/bsd_glob/;
19              
20             # map namespace always to the newest implementation of the protocol
21             my %ns2version =
22             ( &NS_GML => '3.1.1'
23             , &NS_GML_32 => '3.2.1'
24             );
25              
26             # list all available versions
27             my %info =
28             ( '2.0.0' => { prefixes => {gml => NS_GML_200}
29             , schemas => [ 'gml2.0.0/*.xsd' ] }
30             , '2.1.1' => { prefixes => {gml => NS_GML_211}
31             , schemas => [ 'gml2.1.1/*.xsd' ] }
32             , '2.1.2' => { prefixes => {gml => NS_GML_212}
33             , schemas => [ 'gml2.1.2/*.xsd' ] }
34             , '2.1.2.0' => { prefixes => {gml => NS_GML_2120}
35             , schemas => [ 'gml2.1.2.0/*.xsd' ] }
36             , '2.1.2.1' => { prefixes => {gml => NS_GML_2121}
37             , schemas => [ 'gml2.1.2.1/*.xsd' ] }
38             , '3.0.0' => { prefixes => {gml => NS_GML_300, smil => NS_SMIL_20}
39             , schemas => [ 'gml3.0.0/*/*.xsd' ] }
40             , '3.0.1' => { prefixes => {gml => NS_GML_301, smil => NS_SMIL_20}
41             , schemas => [ 'gml3.0.1/*/*.xsd' ] }
42             , '3.1.0' => { prefixes => {gml => NS_GML_310, smil => NS_SMIL_20}
43             , schemas => [ 'gml3.1.0/*/*.xsd' ] }
44             , '3.1.1' => { prefixes => {gml => NS_GML_311, smil => NS_SMIL_20
45             ,gmlsf => NS_GML_311_SF}
46             , schemas => [ 'gml3.1.1/{base,smil,xlink}/*.xsd'
47             , 'gml3.1.1/profile/*/*/*.xsd' ] }
48             , '3.2.1' => { prefixes => {gml => NS_GML_321, smil => NS_SMIL_20 }
49             , schemas => [ 'gml3.2.1/*.xsd', 'gml3.1.1/smil/*.xsd' ] }
50             );
51              
52             # This list must be extended, but I do not know what people need.
53             my @declare_always =
54             qw/gml:TopoSurface/;
55              
56             # for Geo::EOP and other stripped-down GML versions
57             sub _register_gml_version($$) { $info{$_[1]} = $_[2] }
58              
59              
60             sub new($@)
61             { my ($class, $dir) = (shift, shift);
62             $class->SUPER::new(direction => $dir, @_);
63             }
64              
65             sub init($)
66             { my ($self, $args) = @_;
67             $args->{allow_undeclared} = 1
68             unless exists $args->{allow_undeclared};
69              
70             $args->{opts_rw} = +{ @{$args->{opts_rw}} }
71             if ref $args->{opts_rw} eq 'ARRAY';
72             $args->{opts_rw}{key_rewrite} = 'PREFIXED';
73             $args->{opts_rw}{mixed_elements} = 'STRUCTURAL';
74              
75             $args->{any_element} ||= 'ATTEMPT';
76              
77             $self->SUPER::init($args);
78              
79             $self->{GG_dir} = $args->{direction} or panic "no direction";
80              
81             my $version = $args->{version}
82             or error __x"GML object requires an explicit version";
83              
84             unless(exists $info{$version})
85             { exists $ns2version{$version}
86             or error __x"GML version {v} not recognized", v => $version;
87             $version = $ns2version{$version};
88             }
89             $self->{GG_version} = $version;
90             my $info = $info{$version};
91              
92             $self->addPrefixes(xlink => NS_XLINK_1999, %{$info->{prefixes}});
93              
94             (my $xsd = __FILE__) =~ s!\.pm!/xsd!;
95             my @xsds = map bsd_glob("$xsd/$_")
96             , @{$info->{schemas} || []}, 'xlink1.0.0/*.xsd';
97              
98             $self->importDefinitions(\@xsds);
99             $self;
100             }
101              
102             sub declare(@)
103             { my $self = shift;
104              
105             my $direction = $self->direction;
106              
107             $self->declare($direction, $_)
108             for @_, @declare_always;
109              
110             $self;
111             }
112              
113              
114             sub from($@)
115             { my ($class, $data, %args) = @_;
116             my $xml = XML::Compile->dataToXML($data);
117              
118             my $top = type_of_node $xml;
119             my $ns = (unpack_type $top)[0];
120              
121             my $version = $ns2version{$ns}
122             or error __x"unknown GML version with namespace {ns}", ns => $ns;
123              
124             my $self = $class->new('READER', version => $version);
125             my $r = $self->reader($top, %args)
126             or error __x"root node `{top}' not recognized", top => $top;
127              
128             ($top, $r->($xml));
129             }
130              
131             #---------------------------------
132              
133              
134             sub version() {shift->{GG_version}}
135             sub direction() {shift->{GG_dir}}
136              
137             #---------------------------------
138              
139              
140             # just added as example, implemented in super-class
141              
142             #------------------
143              
144              
145             sub printIndex(@)
146             { my $self = shift;
147             my $fh = @_ % 2 ? shift : select;
148             $self->SUPER::printIndex($fh
149             , kinds => 'element', list_abstract => 0, @_);
150             }
151              
152             our $AUTOLOAD;
153             sub AUTOLOAD(@)
154             { my $self = shift;
155             my $call = $AUTOLOAD;
156             return if $call =~ m/::DESTROY$/;
157             my ($pkg, $method) = $call =~ m/(.+)\:\:([^:]+)$/;
158             $method eq 'GPtoGML'
159             or error __x"method {name} not implemented", name => $call;
160             eval "require Geo::GML::GeoPoint";
161             panic $@ if $@;
162             $self->$call(@_);
163             }
164              
165             1;