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