File Coverage

blib/lib/WebService/Mappoint.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package WebService::Mappoint;
2 1     1   3661 use SOAP::Lite;
  0            
  0            
3             use FileHandle;
4             use fields qw(ini_file remote_object CustomerInfoHeader UserInfoHeader);
5             use vars qw(%FIELDS);
6             use vars qw($VERSION);
7             $VERSION=0.30;
8              
9             # @drawmap_EU might be incomplete. It might also contain values that should not be here. Please let me know if there is something wrong
10             my @EU = (qw(
11             ad al am at az by ba be bg hr ch cy cz de dk ee es fo fr fi gb ge gi gr hu is ie it lv lt lu mt nl no pl pt ro sk si se tr ua uk yu
12             ));
13             my %EU;
14             my %NA = (us=>1, ca=>1, mx=>1);
15            
16             use strict;
17              
18             my $ini_files = {};
19             my ( $user, $password );
20              
21             my $default_ini_path;
22              
23             BEGIN {
24            
25             $default_ini_path = $^O =~ m/windows/i ? 'c:\mappoint.ini' : '/etc/mappoint.ini';
26             }
27              
28             ##############################################################################
29             sub new {
30             my ( $class, $proxy_url, $inifile_path ) = @_;
31              
32             no strict 'refs';
33             my $self = bless [\%{"${class}::FIELDS"}], $class;
34              
35             $self->{ini_file} = $inifile_path;
36              
37             if ( $ini_files->{$self->{ini_file}}{debug}{proxy} ) {
38             $proxy_url = $ini_files->{$self->{ini_file}}{debug}{proxy}
39             }
40             die "There is no proxy defined\n" if (!$proxy_url);
41              
42             $self->{remote_object} = SOAP::Lite
43             ->on_action( sub{ $ini_files->{$self->{ini_file}}{xmlns} . $_[1]; })
44             ->proxy($proxy_url)
45             ->envprefix('soap')
46             ->on_fault(
47             sub {
48             my($soap, $res) = @_;
49             die ref $res ? $res->faultdetail : $soap->transport->status, "\n";
50             }
51             )
52             ;
53             # when autotype is switched of, also character escaping is switched off :-/
54             # we added encoding in the handle_*_parameter methods.
55             $self->{remote_object}->serializer()->autotype(0);
56              
57             if ( $ini_files->{$self->{ini_file}}{debug}{readable} ) {
58              
59             $self->{remote_object}->serializer()->readable(1);
60             }
61              
62             return $self;
63             }
64              
65             ##############################################################################
66             # Set header info
67             sub set_CustomLogEntry { $_[0]->{CustomerInfoHeader}{CustomLogEntry} = $_[1]; }
68             sub set_CultureName { $_[0]->{UserInfoHeader}{Culture}{Name} = $_[1]; }
69             sub set_CultureLCID { $_[0]->{UserInfoHeader}{Culture}{LCID} = $_[1]; }
70             sub set_DefaultDistanceUnit { $_[0]->{UserInfoHeader}{DefaultDistanceUnit} = $_[1]; }
71             sub set_ContectGeoID { $_[0]->{UserInfoHeader}{Context}{GeoID} = $_[1]; }
72             sub set_ContectGeoISO2 { $_[0]->{UserInfoHeader}{Context}{GeoISO2} = $_[1]; }
73             ##############################################################################
74             sub method {
75             my ($self, $name, %args) = @_;
76              
77             # we need to set the credentials to be used in this call
78             # so that SOAP::Transport::HTTP::Client::get_basic_credentials
79             # returns the ones corresponding to the ini-file of this
80             # object --How else could we achieve this that is less convoluted?
81             $user = $ini_files->{$self->{ini_file}}{user};
82             $password = $ini_files->{$self->{ini_file}}{password};
83              
84             return $self->{remote_object}
85             ->call(
86             SOAP::Data->name($name)
87             ->attr({ xmlns => $ini_files->{$self->{ini_file}}{xmlns} })
88             => (@{handle_parameters(%args)}, @{$self->header()})
89             );
90             }
91             ##############################################################################
92             sub header {
93             my ($self) = @_;
94              
95             # handle data from ini-file
96             if ($ini_files->{$self->{ini_file}}{culture}) {
97             $self->{UserInfoHeader} ||= {};
98             $self->{UserInfoHeader}{Culture} ||= {};
99             map( $self->{UserInfoHeader}{Culture}{$_} ||= $ini_files->{$self->{ini_file}}{culture}->{$_}, keys %{$ini_files->{$self->{ini_file}}{culture}} );
100             }
101              
102             if ($ini_files->{$self->{ini_file}}{userinfoheader} ) {
103             $self->{UserInfoHeader} ||= {};
104             map($self->{UserInfoHeader}{$_} ||= $ini_files->{$self->{ini_file}}{userinfoheader}->{$_}, keys %{$ini_files->{$self->{ini_file}}{userinfoheader}});
105             }
106              
107             my @header = ();;
108             if ($self->{CustomerInfoHeader}) {
109             push(@header,
110             SOAP::Header->name('CustomerInfoHeader' => \SOAP::Header->value(
111             @{handle_header_parameters(%{$self->{CustomerInfoHeader}})}
112             ))->attr({xmlns => $ini_files->{$self->{ini_file}}{xmlns}})
113             );
114             }
115             if ($self->{UserInfoHeader}) {
116             my @param;
117             push(@header,
118             SOAP::Header->name('UserInfoHeader' => \SOAP::Header->value(
119             @{handle_header_parameters(%{$self->{UserInfoHeader}})}
120             ))->attr({xmlns => $ini_files->{$self->{ini_file}}{xmlns}})
121             );
122             }
123              
124             return \@header;
125             }
126             ##############################################################################
127             sub parse_ini_file {
128             my $fname = shift;
129              
130             # don't do anything if file has already been parsed
131             if ( exists $ini_files->{$fname}{user} ) { return }
132            
133             my $fh = new FileHandle($fname, 'r');
134             die "No ini-file ($fname) found\n" if (!$fh);
135            
136             my (%sec, $sec);
137             while(my $line = <$fh>) {
138             $line = strip($line);
139             next if (substr($line, 0, 1) eq ';');
140             if ($line =~ m/^\[/ && $line =~ m/\]$/) {
141             $sec = lc(strip(substr($line,1,length($line)-2)));
142             }
143             elsif ($line =~ m/=/) {
144             die "put [section]-line in the ini-file\n" if (!$sec);
145             my ($param,$value) = ($line =~ m/(\S+)\s*=\s*(\S*)$/);
146             $sec{$sec} ||= {};
147             $sec{$sec}{$param} = $value;
148             }
149             else {
150             die "Weird line in mappoint.ini: $line\n" if ($line !~ m/^\s*$/);
151             }
152             }
153             die "No credentials section in ini-file\n" if (!$sec{credentials});
154             $ini_files->{$fname}{xmlns} = $sec{general}{xmlns}
155             || die "put a 'xmlns=...' in the general section in the ini-file\n";
156             $ini_files->{$fname}{user} = $sec{credentials}{user}
157             || die "put 'user=...' in credentials section in ini-file\n";
158             $ini_files->{$fname}{password} = $sec{credentials}{password}
159             || die "put 'password=...' in credentials section in ini-file\n";
160             $ini_files->{$fname}{proxy} = $sec{proxy};
161             $ini_files->{$fname}{culture} = $sec{culture};
162             $ini_files->{$fname}{debug} = $sec{debug};
163             $ini_files->{$fname}{userinfoheader} = $sec{userinfoheader};
164             }
165              
166             ##############################################################################
167             sub strip { my $s = shift; $s =~ s/^\s+//; $s =~ s/\s+$//; return $s }
168             ##############################################################################
169             sub encode { SOAP::Utils::encode_data(@_); }
170             ##############################################################################
171             sub handle_header_parameters {
172             my (%args) = @_;
173             my @parameters;
174             foreach my $k (keys %args) {
175             if (ref($args{$k}) eq 'HASH') {
176             push(@parameters, SOAP::Header->name($k => \SOAP::Header->value(
177             @{handle_header_parameters(%{$args{$k}})}
178             )));
179             }
180             else {
181             push(@parameters, SOAP::Header->name($k => encode($args{$k})));
182             }
183             }
184             return \@parameters;
185             }
186             ##############################################################################
187             sub handle_parameters {
188             my (%args) = @_;
189             my @parameters;
190             foreach my $k (keys %args) {
191             if (ref($args{$k}) eq 'ARRAY') {
192             my @data = @{$args{$k}};
193             my @params;
194             while (scalar(@data) > 0) {
195             my ($key, $value) = (shift(@data), shift(@data));
196             push(@params, @{handle_parameters($key => $value)});
197             }
198              
199             if( $k =~ /:/ ) {
200             my( $type, $subtype ) = split( /:/, $k );
201            
202             push(@parameters, SOAP::Data->name( $type => \SOAP::Data->value(
203             @params
204             ) )->attr( { 'xsi:type' => $subtype } ) );
205            
206             } else {
207            
208             push(@parameters, SOAP::Data->name($k => \SOAP::Data->value(
209             @params
210             )));
211             }
212             }
213             elsif (ref($args{$k}) eq 'HASH') {
214             push(@parameters, SOAP::Data->name($k)->attr( $args{$k}));
215             }
216             else {
217             # if ($args{$k} eq 'true' || $args{$k} eq 'false') {
218             # push(@parameters, SOAP::Data->name($k => $args{$k})->type('bool'));
219             # }
220             # else {
221             push(@parameters, SOAP::Data->name($k => encode($args{$k})));
222             # }
223             }
224             }
225              
226             # use Data::Dumper;
227             # print STDERR "PARAMETROS:\n";
228             # print STDERR Dumper(\@parameters);
229              
230             return \@parameters;
231             }
232             ##############################################################################
233             sub drawmap_for_country {
234             # take last argument, so that this method can be use as function as well
235             # as class/instance method
236             my $country = lc(pop(@_));
237             print STDERR ("country code: $country\n");
238             map($EU{$_}=1, @EU) if (!exists($EU{nl}));
239             return 'MapPoint.EU' if $EU{$country};
240             return 'MapPoint.NA' if $NA{$country};
241             return 'MapPoint.World';
242             }
243             ##############################################################################
244             sub address_datasource {
245             my $country = lc(pop(@_));
246             map($EU{$_}=1, @EU) if (!exists($EU{nl}));
247             return 'MapPoint.EU' if $EU{$country};
248             return 'MapPoint.NA' if $NA{$country};
249             return '';
250             }
251             ##############################################################################
252             #BEGIN { parse_ini_file(); }
253             ##############################################################################
254              
255             ##############################################################################
256             package WebService::Mappoint::Common;
257             use base qw(WebService::Mappoint);
258             ##############################################################################
259             sub new {
260             my $class = shift;
261             my $inifile_path =
262             shift || $default_ini_path;
263            
264             WebService::Mappoint::parse_ini_file( $inifile_path );
265            
266             return $class->SUPER::new( $ini_files->{ $inifile_path }{proxy}{common}, $inifile_path );
267             }
268             sub GetEntityTypesProperties { return shift->method('GetEntityTypesProperties', @_); }
269             sub GetGeoCountryRegionInfo { return shift->method('GetGeoCountryRegionInfo', @_); }
270             sub GetGreatCircleDistances { return shift->method('GetGreatCircleDistances', @_); }
271             sub GetDataSourceInfo { return shift->method('GetDataSourceInfo', @_); }
272             sub GetVersionInfo { return shift->method('GetVersionInfo', @_); }
273              
274             # methods new to 3.0
275             sub GetCountryRegionInfo { return shift->method('GetCountryRegionInfo', @_); }
276             sub GetEntityTypes { return shift->method('GetEntityTypes', @_); }
277              
278              
279             ##############################################################################
280             package WebService::Mappoint::Render;
281             use base qw(WebService::Mappoint);
282             ##############################################################################
283             sub new {
284             my $class = shift;
285             my $inifile_path =
286             shift || $default_ini_path;
287            
288             WebService::Mappoint::parse_ini_file( $inifile_path );
289              
290             return $class->SUPER::new( $ini_files->{ $inifile_path }{proxy}{render}, $inifile_path );
291             }
292             sub GetMap { return shift->method('GetMap', @_); }
293             sub GetBestMapView { return shift->method('GetBestMapView', @_); }
294             sub ConvertToPoint { return shift->method('ConvertToPoint', @_); }
295             sub ConvertToLatLong { return shift->method('ConvertToLatLong', @_); }
296              
297             # methods exclusive to 2.0 servers
298             sub GetRouteMap { return shift->method('GetRouteMap', @_); }
299             sub GetBoundingMap { return shift->method('GetBoundingMap', @_); }
300              
301              
302             ##############################################################################
303             package WebService::Mappoint::Find;
304             use base qw(WebService::Mappoint);
305             ##############################################################################
306             sub new {
307             my $class = shift;
308             my $inifile_path =
309             shift || $default_ini_path;
310            
311             WebService::Mappoint::parse_ini_file( $inifile_path );
312              
313             return $class->SUPER::new( $ini_files->{ $inifile_path }{proxy}{find}, $inifile_path );
314             }
315             sub FindNearby { return shift->method('FindNearby', @_); }
316             sub FindAddress { return shift->method('FindAddress', @_); }
317             sub Find { return shift->method('Find', @_); }
318              
319             # methods new in 3.0
320             sub GetLocationInfo { return shift->method('GetLocationInfo', @_); }
321             sub ParseAddress { return shift->method('ParseAddress', @_); }
322              
323             ##############################################################################
324             package WebService::Mappoint::Route;
325             use base qw(WebService::Mappoint);
326             ##############################################################################
327             sub new {
328             my $class = shift;
329             my $inifile_path =
330             shift || $default_ini_path;
331            
332             WebService::Mappoint::parse_ini_file( $inifile_path );
333              
334             return $class->SUPER::new( $ini_files->{ $inifile_path }{proxy}{route}, $inifile_path );
335             }
336              
337             sub CalculateRoute { return shift->method('CalculateRoute', @_); }
338             sub CalculateSimpleRoute { return shift->method('CalculateSimpleRoute', @_); }
339              
340              
341             ##############################################################################
342             package WebService::Mappoint::ResultElement;
343             #use fields qw(name attr subitems);
344             #use vars qw(%FIELDS);
345             ##############################################################################
346             sub new {
347             my ($class, %args) = @_;
348             no strict 'refs';
349             # my $self = bless [\%{"${class}::FIELDS"}], $class;
350             my $self = bless {}, $class;
351             map($self->{$_} = $args{$_}, keys %args);
352             return $self;
353             }
354             ##############################################################################
355             sub name { return shift->{name}; }
356             sub attr { return shift->{attr}; }
357             sub subitems { return shift->{subitems} || []; }
358             sub get { return $_[0]->{attr}{$_[1]}; }
359             sub add_sub {
360             my ($self, $elm) = @_;
361             $self->{subitems} ||= [];
362             push(@{$self->{subitems}}, $elm);
363             }
364            
365              
366             ##############################################################################
367             package WebService::Mappoint::Result;
368             use fields qw(_content _tree);
369             use vars qw(%FIELDS);
370             ##############################################################################
371             sub new {
372             my ($class, $som) = @_;
373             no strict 'refs';
374             my $self = bless [\%{"${class}::FIELDS"}], $class;
375             $self->{_content} = $som->{_content};
376             $self->build_tree();
377             return $self;
378             }
379             ##############################################################################
380             sub show_content {
381             my ($self) = @_;
382             _show_content($self->{_content}, 0);
383             }
384             ##############################################################################
385             sub _show_content {
386             my ($s, $level) = @_;
387             my $indent = ' ';
388             if (ref($s->[0])) {
389             foreach my $e (@$s) {
390             _show_content($e, $level+1);
391             }
392             }
393             elsif ($s->[0]) {
394             if (ref($s->[2])) {
395             print STDERR ($indent x $level, $s->[0], "\n");
396             _show_content($s->[2], $level+1);
397             }
398             else {
399             if ($s->[2]) {
400             print STDERR ($indent x $level, $s->[0], ': ', $s->[2], "\n");
401             }
402             if (scalar(keys %{$s->[1]}) > 0) {
403             print STDERR ($indent x $level, $s->[0], "\n") if (!$s->[2]);
404             foreach my $k (keys %{$s->[1]}) {
405             print STDERR ($indent x($level+1), $k, ': ', $s->[1]{$k}, "\n");
406             }
407             }
408             }
409             }
410             }
411             ##############################################################################
412             sub build_tree {
413             my ($self) = @_;
414             $self->{_tree} = _build_tree($self->{_content});
415             _clean_up_tree($self->{_tree});
416             }
417             ##############################################################################
418             sub _build_tree {
419             my ($s, $parent) = @_;
420             my ($name, $attr, $value) = @$s;
421             if (!ref($name)) {
422             # if it's only a name-value pair, its an attribute of the parent
423             if (scalar(keys %$attr) == 0 && !ref($value)) {
424             $parent->{attr}{$name} = $value;
425             return;
426             }
427             my $elm = new WebService::Mappoint::ResultElement(name => $s->[0], attr => $s->[1]);
428             if (ref($value) eq 'ARRAY') {
429             _build_tree($value, $elm);
430             }
431             if ($parent) {
432             $parent->add_sub($elm);
433             }
434             else {
435             return $elm; # root object
436             }
437             }
438             else {
439             foreach my $e (@$s) {
440             _build_tree($e, $parent);
441             }
442             }
443             }
444             ##############################################################################
445             sub _clean_up_tree {
446             my ($elm) = @_;
447             my %name;
448             foreach my $sub (@{$elm->subitems}) {
449             if (scalar(@{$sub->subitems}) == 0) {
450             $name{$sub->name}++;
451             }
452             }
453             my @newsubitems;
454             foreach my $sub (@{$elm->subitems}) {
455             if ($name{$sub->name} && $name{$sub->name} == 1) {
456             # print("cleaning up ", $sub->name, "\n");
457             $elm->{attr}{$sub->name} = $sub->{attr};
458             }
459             else {
460             push(@newsubitems, $sub);
461             }
462             }
463             $elm->{subitems} = \@newsubitems;
464             foreach my $sub (@{$elm->subitems}) {
465             _clean_up_tree($sub);
466             }
467             }
468             ##############################################################################
469             sub show {
470             my ($self, $tree) = @_;
471             $tree ||= $self->{_tree};
472             _show($tree, 0);
473             }
474             ##############################################################################
475             sub _show {
476             my ($elm, $level) = @_;
477             my $indent=' ';
478             print STDERR ($indent x $level, $elm->name, "\n");
479             foreach my $k (sort keys %{$elm->attr}) {
480             my $value = $elm->{attr}{$k};
481             if (ref($value)) {
482             $value = join(', ', map($_ . ': ' . $value->{$_}, keys %$value));
483             $value = "($value)";
484             }
485             print STDERR ($indent x ($level+1), $k, ': ', $value, "\n");
486             }
487             foreach my $sub (@{$elm->subitems}) {
488             _show($sub, $level+1);
489             }
490             }
491             ##############################################################################
492             sub get_first {
493             my ($self, $name, $tree) = @_;
494             $tree ||= $self->{_tree};
495             return _get_first($tree, $name);
496             }
497             ##############################################################################
498             sub _get_first {
499             my ($elm, $name) = @_;
500             return undef if (!$elm);
501             return $elm if ($elm->name eq $name);
502             foreach my $e (@{$elm->subitems}) {
503             my $t = _get_first($e, $name);
504             return $t if ($t);
505             }
506             return undef;
507             }
508              
509              
510             ##############################################################################
511             package main;
512             sub SOAP::Transport::HTTP::Client::get_basic_credentials {
513              
514             return $user => $password;
515             }
516             ##############################################################################
517              
518             1;
519              
520             __END__