File Coverage

blib/lib/Geo/Coder/GoogleMaps/Location.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Geo::Coder::GoogleMaps::Location ;
2              
3 4     4   95659 use strict;
  4         10  
  4         154  
4 4     4   24 use warnings;
  4         9  
  4         183  
5 4     4   21 use strict;
  4         7  
  4         146  
6 4     4   24 use Carp;
  4         6  
  4         401  
7 4     4   3819 use JSON::Syck;
  4         20934  
  4         225  
8 4     4   1907 use XML::LibXML;
  0            
  0            
9              
10             our $VERSION='0.4';
11              
12             =encoding utf-8
13              
14             =head1 NAME
15              
16             Geo::Coder::GoogleMaps::Location - Geo::Coder::GoogleMaps' Location object
17              
18             =head1 VERSION
19              
20             Version 0.4 (follow L version number)
21              
22             =head1 SYNOPSIS
23              
24             Here we have the object returned by L->placemarks().
25              
26             This object can generate and manipulate the geocoding subset of KML 2.2 object (main change for the geocoding feature is the introduction of ExtendedData).
27              
28             =head1 FUNCTIONS
29              
30             =head2 new
31              
32             The constructor can take the following arguments :
33              
34             - SubAdministrativeAreaName : a string
35             - PostalCodeNumber : a postal code (err...)
36             - LocalityName : yes! A locality name !
37             - ThoroughfareName: same thing => a string
38             - AdministrativeAreaName
39             - CountryName
40             - CountryNameCode
41             - address
42             - longitude
43             - latitude
44             - altitude (warning in Google Maps API altitude must be 0)
45              
46             =cut
47              
48             sub new {
49             my($class, %param) = @_;
50             my $obj = {
51             'AddressDetails' => {
52             'Country' => {
53             'AdministrativeArea' => {
54             'SubAdministrativeArea' => {
55             'SubAdministrativeAreaName' => delete $param{'SubAdministrativeAreaName'} || '',
56             'Locality' => {
57             'PostalCode' => {
58             'PostalCodeNumber' => delete $param{'PostalCodeNumber'} || ''
59             },
60             'LocalityName' => delete $param{'LocalityName'} || '',
61             'Thoroughfare' => {
62             'ThoroughfareName' => delete $param{'ThoroughfareName'} || ''
63             }
64             }
65             },
66             'AdministrativeAreaName' => delete $param{'AdministrativeAreaName'} || ''
67             },
68             'CountryNameCode' => delete $param{'CountryNameCode'} || '',
69             'CountryName' => delete $param{'CountryName'} || ''
70             }
71             },
72             'address' => delete $param{'address'} || '',
73             'Point' => {
74             'coordinates' => [
75             delete $param{'longitude'} || '',
76             delete $param{'latitude'} || '',
77             delete $param{'altitude'} || 0
78             ]
79             }
80             };
81             my $out = delete $param{'output'} || 'json';
82             bless { data => $obj, output => $out }, $class;
83             }
84              
85             =head2 SubAdministrativeAreaName
86              
87             Access the SubAdministrativeAreaName parameter.
88              
89             print $location->SubAdministrativeAreaName(); # retrieve the value
90             $location->SubAdministrativeAreaName("Paris"); # set the value
91              
92             =cut
93              
94             sub SubAdministrativeAreaName {
95             my ($self,$data) = @_ ;
96             return $data ? $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'SubAdministrativeAreaName'}=$data : $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'SubAdministrativeAreaName'} ;
97             }
98              
99             =head2 PostalCodeNumber
100              
101             Access the PostalCodeNumber parameter.
102              
103             print $location->PostalCodeNumber(); # retrieve the value
104             $location->PostalCodeNumber("75000"); # set the value
105              
106             =cut
107              
108             sub PostalCodeNumber {
109             my ($self,$data) = @_ ;
110             return $data ? $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'Locality'}->{'PostalCode'}->{'PostalCodeNumber'}=$data : $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'Locality'}->{'PostalCode'}->{'PostalCodeNumber'} ;
111             }
112              
113             =head2 ThoroughfareName
114              
115             Access the ThoroughfareName parameter.
116              
117             print $location->ThoroughfareName(); # retrieve the value
118             $location->ThoroughfareName("1 Avenue des Champs Élysées"); # set the value
119              
120             =cut
121              
122             sub ThoroughfareName {
123             my ($self,$data) = @_ ;
124             return $data ? $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'Locality'}->{'Thoroughfare'}->{'ThoroughfareName'}=$data : $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'Locality'}->{'Thoroughfare'}->{'ThoroughfareName'} ;
125             }
126              
127             =head2 LocalityName
128              
129             Access the LocalityName parameter.
130              
131             print $location->LocalityName(); # retrieve the value
132             $location->LocalityName("Paris"); # set the value
133              
134             =cut
135              
136             sub LocalityName {
137             my ($self,$data) = @_ ;
138             return $data ? $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'Locality'}->{'LocalityName'}=$data : $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'SubAdministrativeArea'}->{'Locality'}->{'LocalityName'} ;
139             }
140              
141             =head2 AdministrativeAreaName
142              
143             Access the AdministrativeAreaName parameter.
144              
145             print $location->AdministrativeAreaName(); # retrieve the value
146             $location->AdministrativeAreaName("PA"); # set the value
147              
148             =cut
149              
150             sub AdministrativeAreaName {
151             my ($self,$data) = @_ ;
152             return $data ? $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'AdministrativeAreaName'}=$data : $self->{data}->{'AddressDetails'}->{'Country'}->{'AdministrativeArea'}->{'AdministrativeAreaName'} ;
153             }
154              
155             =head2 CountryName
156              
157             Access the CountryName parameter.
158              
159             print $location->CountryName(); # retrieve the value
160             $location->CountryName("France"); # set the value
161              
162             =cut
163              
164             sub CountryName {
165             my ($self,$data) = @_ ;
166             return $data ? $self->{data}->{'AddressDetails'}->{'Country'}->{'CountryName'}=$data : $self->{data}->{'AddressDetails'}->{'Country'}->{'CountryName'} ;
167             }
168              
169             =head2 CountryNameCode
170              
171             Access the CountryNameCode parameter.
172              
173             print $location->CountryNameCode(); # retrieve the value
174             $location->CountryNameCode("FR"); # set the value
175              
176             =cut
177              
178             sub CountryNameCode {
179             my ($self,$data) = @_ ;
180             return $data ? $self->{data}->{'AddressDetails'}->{'Country'}->{'CountryNameCode'}=$data : $self->{data}->{'AddressDetails'}->{'Country'}->{'CountryNameCode'} ;
181             }
182              
183             =head2 Accuracy
184              
185             Access the Accuracy parameter.
186              
187             print $location->Accuracy(); # retrieve the value
188             $location->Accuracy(8); # set the value
189              
190             =cut
191              
192             sub Accuracy {
193             my ($self,$data) = @_ ;
194             return $data ? $self->{data}->{'AddressDetails'}->{'Accuracy'}=$data : $self->{data}->{'AddressDetails'}->{'Accuracy'} ;
195             }
196              
197             =head2 address
198              
199             Access the address parameter.
200              
201             print $location->address(); # retrieve the value
202             $location->address("1 Avenue des Champs Élysées, 75000, Paris, FR"); # set the value
203              
204             =cut
205              
206             sub address {
207             my ($self,$data) = @_ ;
208             return $data ? $self->{data}->{'address'}=$data : $self->{data}->{'address'} ;
209             }
210              
211             =head2 id
212              
213             Access the id parameter.
214              
215             print $location->id(); # retrieve the value
216             $location->id("point1"); # set the value
217              
218             =cut
219              
220             sub id {
221             my ($self,$data) = @_ ;
222             return $data ? $self->{data}->{'id'}=$data : $self->{data}->{'id'} ;
223             }
224              
225             =head2 latitude
226              
227             Access the latitude parameter.
228              
229             print $location->latitude(); # retrieve the value
230             $location->latitude("-122.4558"); # set the value
231              
232             =cut
233              
234             sub latitude {
235             my ($self,$data) = @_ ;
236             return $data ? $self->{data}->{'Point'}->{'coordinates'}->[1]=$data : $self->{data}->{'Point'}->{'coordinates'}->[1] ;
237             }
238              
239              
240             =head2 longitude
241              
242             Access the longitude parameter.
243              
244             print $location->longitude(); # retrieve the value
245             $location->longitude("55.23465"); # set the value
246              
247             =cut
248              
249             sub longitude {
250             my ($self,$data) = @_ ;
251             return $data ? $self->{data}->{'Point'}->{'coordinates'}->[0]=$data : $self->{data}->{'Point'}->{'coordinates'}->[0] ;
252             }
253              
254             =head2 altitude
255              
256             Access the altitude parameter.
257              
258             print $location->altitude(); # retrieve the value
259             $location->altitude(0); # set the value
260              
261             Please note that it must be 0 if you use the Google Map API.
262              
263             =cut
264              
265             sub altitude {
266             my ($self,$data) = @_ ;
267             return $data ? $self->{data}->{'Point'}->{'coordinates'}->[2]=$data : $self->{data}->{'Point'}->{'coordinates'}->[2] ;
268             }
269              
270             =head2 coordinates
271              
272             This method is not really an accessor, it's only a getter which return longitude, latitude and altitude as a string.
273              
274             print "Placemark's coordinates: ",$location->coordinates,"\n";
275              
276             =cut
277              
278             sub coordinates {
279             my $self = shift;
280             return $self->longitude().','.$self->latitude().','.$self->altitude ;
281             }
282              
283             =head2 LLB_north
284              
285             Access the north parameter from the LatLonBox.
286              
287             print $location->LLB_north(); # retrieve the value
288             $location->LLB_north(48.9157461); # set the value
289              
290             =cut
291              
292             sub LLB_north {
293             my ($self,$data) = @_ ;
294             return $data ? $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'north'}=$data : $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'north'} ;
295             }
296              
297             =head2 LLB_south
298              
299             Access the south parameter from the LatLonBox.
300              
301             print $location->LLB_south(); # retrieve the value
302             $location->LLB_south(48.9157461); # set the value
303              
304             =cut
305              
306             sub LLB_south {
307             my ($self,$data) = @_ ;
308             return $data ? $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'south'}=$data : $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'south'} ;
309             }
310              
311             =head2 LLB_east
312              
313             Access the east parameter from the LatLonBox.
314              
315             print $location->LLB_east(); # retrieve the value
316             $location->LLB_east(48.9157461); # set the value
317              
318             =cut
319              
320             sub LLB_east {
321             my ($self,$data) = @_ ;
322             return $data ? $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'east'}=$data : $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'east'} ;
323             }
324              
325             =head2 LLB_west
326              
327             Access the west parameter from the LatLonBox.
328              
329             print $location->LLB_west(); # retrieve the value
330             $location->LLB_west(48.9157461); # set the value
331              
332             =cut
333              
334             sub LLB_west {
335             my ($self,$data) = @_ ;
336             return $data ? $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'west'}=$data : $self->{data}->{'ExtendedData'}->{'LatLonBox'}->{'west'} ;
337             }
338              
339             =head2 toJSON
340              
341             Return a JSON encoded object ( thanks to JSON::Syck::Dump() )
342              
343             my $json = $location->toJSON ;
344              
345             =cut
346              
347             sub toJSON {
348             my $self = shift;
349             return JSON::Syck::Dump($self->{'data'}) ;
350             }
351              
352             =head2 toKML
353              
354             Return a KML object ( thanks to XML::LibXML ).
355              
356             my $kml = $location->toXML ;
357              
358             Please note that this function can take an optionnal argument (0 or 1) and if it's set to 1 this method return a XML string instead of the XML::LibXML::Document object.
359              
360             =cut
361              
362             sub toKML {
363             sub _toKMLinternal {
364             my $self = shift;
365             my $document = shift;
366             my $xml_element = shift;
367             my $root = shift;
368             return unless($root);
369             return unless( ref($root) eq "HASH" );
370             # print "[debug] _toKMLinternal() \$root=$root\n";
371             foreach my $key (keys(%{$root})){
372             next if($key eq "Accuracy");
373             # print "[debug] _toKMLinternal() creating new element: $key\n";
374             my $new_element = $document->createElement($key);
375             if( $self->can($key) ){
376             if(defined($self->$key)){
377             $new_element->appendText($self->$key);
378             $xml_element->appendChild($new_element);
379             }
380             }
381             else{
382             if($key eq 'AddressDetails'){
383             $new_element->setNamespace("urn:oasis:names:tc:ciq:xsdschema:xAL:2.0", '',0);
384             $new_element->setAttribute('Accuracy',$self->Accuracy);
385             }
386             elsif( $key eq 'LatLonBox' ){
387             $new_element->setAttribute('north',$root->{$key}->{north});
388             $new_element->setAttribute('south',$root->{$key}->{south});
389             $new_element->setAttribute('east',$root->{$key}->{east});
390             $new_element->setAttribute('west',$root->{$key}->{west});
391             }
392             $xml_element->appendChild($new_element);
393             _toKMLinternal($self,$document,$new_element,$root->{$key}) unless($key eq 'LatLonBox');
394             }
395             }
396             }
397            
398             my $self = shift;
399             my $as_string = shift;
400             my $document = XML::LibXML::Document->createDocument( "1.0", "UTF-8" );
401             $document->setStandalone(1);
402             my $kml = $document->createElement('kml');
403             # $kml->setNamespace("http://earth.google.com/kml/2.1", '',0);
404             $kml->setNamespace("http://www.opengis.net/kml/2.2", '',0);
405             $document->setDocumentElement($kml);
406             my $placemark = $document->createElement('Placemark');
407             $placemark->setAttribute('id',$self->id);
408             $kml->appendChild($placemark);
409             my $data = {%{$self->{data}}};
410             delete($data->{id});
411             # delete($data->{AddressDetails}->{Accuracy});
412             _toKMLinternal($self,$document,$placemark,$data);
413             $document->setEncoding("UTF-8");
414             return $document->toString(1) if($as_string);
415             return $document;
416             }
417              
418             =head2 toXML
419              
420             An allias for toKML()
421              
422             =cut
423              
424             sub toXML {
425             return shift->toKML(@_);
426             }
427              
428             =head2 Serialize
429              
430             This method simply call the good to(JSON|XML|KML) depending of the output format you selected.
431              
432             You can eventually pass extra arguments, they will be relayed.
433              
434             $location->Serialize(1); # if the output is set to XML or KML you will have a stringified XML as output
435              
436             =cut
437              
438             sub Serialize {
439             my $self = shift;
440             if($self->{output}){
441             return $self->toJSON if($self->{output} eq 'json');
442             return $self->toKML(@_) if($self->{output} eq 'xml' or $self->{output} eq 'kml');
443             return $self->toJSON ;
444             }
445             else {
446             return $self->toJSON ;
447             }
448             }
449              
450             =head2 Serialyze (OBSOLETE)
451              
452             This method is just an alias to Serialize(), it is kept for backward compatibility only.
453              
454             Please use the Serialize() method, this one is meant to be removed.
455              
456             =cut
457              
458             sub Serialyze {
459             return Serialize(@_);
460             }
461              
462             sub _setData {
463             my ($self,$data)=@_;
464             $self->{data}=$data;
465             }
466              
467             =head1 AUTHOR
468              
469             Arnaud Dupuis, C<< >>
470              
471             =head1 BUGS
472              
473             Please report any bugs or feature requests to
474             C, or through the web interface at
475             L.
476             I will be notified, and then you'll automatically be notified of progress on
477             your bug as I make changes.
478              
479             =head1 SUPPORT
480              
481             You can find documentation for this module with the perldoc command.
482              
483             perldoc Geo::Coder::GoogleMaps::Location
484              
485             You can also look for information at:
486              
487             =over 4
488              
489             =item * Infinity Perl:
490              
491             L
492              
493             =item * Google Code repository
494              
495             L
496              
497             =item * Google Maps API documentation
498              
499             L
500              
501             =item * AnnoCPAN: Annotated CPAN documentation
502              
503             L
504              
505             =item * CPAN Ratings
506              
507             L
508              
509             =item * RT: CPAN's request tracker
510              
511             L
512              
513             =item * Search CPAN
514              
515             L
516              
517             =back
518              
519             =head1 ACKNOWLEDGEMENTS
520              
521             Slaven Rezic (L) for all the patches and his useful reports on RT.
522              
523             =head1 COPYRIGHT & LICENSE
524              
525             Copyright 2007 Arnaud DUPUIS and Nabla Development, all rights reserved.
526              
527             This program is free software; you can redistribute it and/or modify it
528             under the same terms as Perl itself.
529              
530             =cut
531             1; # end of Geo::Coder::GoogleMaps::Location