Net-API-Nominatim

 view release on metacpan or  search on metacpan

lib/Net/API/Nominatim.pm  view on Meta::CPAN

use HTTP::CookieJar::LWP;
use HTTP::Cookies;
use HTTP::Request;
use IO::Socket::UNIX qw/SOCK_STREAM SOMAXCONN/;
use Hash::Merge;
use Cookies::Roundtrip qw/lwpuseragent_load_cookies/;
use Storable qw/dclone/;
use Data::Roundtrip qw/perl2dump json2perl no-unicode-escape-permanently/;

use Net::API::Nominatim::Model::Address;

my $__DEFAULT_USERAGENT_STRING = 'Net::API::Nominatim Perl Client v'.$VERSION.' by bliako@cpan.org (thank you OSM)';

sub	new {
	my $class = $_[0];
	my $params = $_[1] // {};
	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];

	# we are deleting items from user-specified params HASH_REF
	# we must clone it BUT there is a problem with objects (e.g. the logger)
	# we do not want to clone them but Clone::clone creates new objects
	# and Storable::dclone complains, so fo.
	#my $params = Storable::dclone($_params);

	my $self = {
	  '_private' => {
		  'log' => {
			'logger-object' => undef,
		  },
		  'lwpuseragent' => {
			'lwpuseragent-object' => undef,
			'cookies-object' => undef,
		  },
	  },
	  'options' => {
		'server' => {
			# we need one of 'url' or 'unix-socket'
			# on init a 'method' will be created holding 'url' or 'unix-socket'
			# do not set any
			#'url' => 'https://nominatim.openstreetmap.org',
			# fullpath to local unix socket:
			#'unix-socket' => 'unix-socket-path', # let the user set it
		},
		'lwpuseragent' => {
			'cookies-filename' => undef,
			# Nominatim's terms of usage requires a unique UA string to identify the client:
			# we also force this if the user specifies a ready-made UA object
			# sorry, I hate to interfere on user-specified objects
			'useragent-string' => $__DEFAULT_USERAGENT_STRING,
		},
		'debug' => {
			'verbosity' => 1,
			'cleanup' => 0,
		},
		'log' => {
			'logger-file' => undef,
		},
	  }
	};
	bless $self => $class;

	if( exists($params->{'verbosity'}) && defined($params->{'verbosity'}) ){
		$self->{'options'}->{'verbosity'} = $params->{'verbosity'}
	}
	my $verbosity = $self->verbosity();

	# WARNING: we are deleting items from user-supplie $params here, so we clone it

	# do we have a logger specified in params?
	if( exists($params->{'log'}->{'logger-file'}) && defined($params->{'log'}->{'logger-file'}) ){
		my $adir = File::Basename::dirname($params->{'log'}->{'logger-file'});
		if( ! -d $adir ){ make_path($adir); if( ! -d $adir ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, logfile directory '$adir' is not a dir or failed to be created.\n"; return undef } }
		$self->{'_private'}->{'log'}->{'logger-object'} = Mojo::Log->new(path => $params->{'log'}->{'logger-file'});
		delete $params->{'log'}->{'logger-file'};
	} elsif( exists($params->{'log'}->{'logger-object'}) && defined($params->{'log'}->{'logger-object'}) ){
		$self->{'_private'}->{'log'}->{'logger-object'} = $params->{'log'}->{'logger-object'};
		delete $params->{'log'}->{'logger-object'};
	} elsif( exists($self->{'options'}->{'log'}) && exists($self->{'options'}->{'logger-file'}) && defined($self->{'options'}->{'logger-file'}) ){
		my $adir = File::Basename::dirname($self->{'options'}->{'logger-file'});
		if( ! -d $adir ){ make_path($adir); if( ! -d $adir ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, logfile directory '$adir' is not a dir or failed to be created.\n"; return undef } }
		$self->{'_private'}->{'log'}->{'logger-object'} = Mojo::Log->new(path => $self->{'options'}->{'logger-file'});
		delete $self->{'options'}->{'log'};
	} else { $self->{'_private'}->{'log'}->{'logger-object'} = Mojo::Log->new() }

	# Now we have a logger
	my $log = $self->log();

	# any objects in params must be migrated now!
	if( exists($params->{'lwpuseragent'}->{'cookies-object'}) && defined($params->{'lwpuseragent'}->{'cookies-object'}) ){
		# NOTE: the cookiejar we pass will be cloned and will not have the same pointer
		$self->{'_private'}->{'lwpuseragent'}->{'cookies-object'} = $params->{'lwpuseragent'}->{'cookies-object'};
	}
	if( exists($params->{'lwpuseragent'}->{'lwpuseragent-object'}) && defined($params->{'lwpuseragent'}->{'lwpuseragent-object'}) ){
		$self->{'_private'}->{'lwpuseragent'}->{'lwpuseragent-object'} = $params->{'lwpuseragent'}->{'lwpuseragent-object'};
	}

	# and add more user-specified params into our self
	# right is our params, left the options
	my $hm = Hash::Merge->new('RIGHT_PRECEDENT');
	$hm->add_behavior_spec({
		'SCALAR' => {
		# left is scalar (above), right is one of these, what to do?:
		# we are only interested in SCALAR/SCALAR, ie left+right
		# can not be different types
		'SCALAR' => sub { defined($_[1]) ? $_[1] : $_[0] },
			'ARRAY'  => sub { if( defined($_[1]) ){  perl2dump($_[0])." and right: ".perl2dump($_[1])."unexpected type SCALAR/ARRAY" } else { $_[0] = $_[1] } },
			'HASH'   => sub { if( defined($_[1]) ){  perl2dump($_[0])." and right: ".perl2dump($_[1])."unexpected type SCALAR/HASH" } else { $_[0] = $_[1] } },
		},
		'ARRAY' => {
		# left is array (above), right is one of these, what to do?:
			'SCALAR' => sub { if( defined($_[1]) ){  perl2dump($_[0])." and right: ".perl2dump($_[1])."unexpected type ARRAY/SCALAR" } else { $_[0] = $_[1] } },
			'ARRAY'  => sub { [ defined($_[1]) ? @{ $_[1] } : @{ $_[0] } ] },
			'HASH'   => sub { if( defined($_[1]) ){  perl2dump($_[0])." and right: ".perl2dump($_[1])."unexpected type ARRAY/HASH" } else { $_[0] = $_[1] } },
		},
		'HASH' => {
		# left is hash (above), right is one of these, what to do?:
			'SCALAR' => sub { if( defined($_[1]) ){  perl2dump($_[0])." and right: ".perl2dump($_[1])."unexpected type HASH/SCALAR" } else { $_[0] = $_[1] } },
			'ARRAY'  => sub { if( defined($_[1]) ){  perl2dump($_[0])." and right: ".perl2dump($_[1])."unexpected type HASH/ARRAY" } else { $_[0] = $_[1] } },
			'HASH'   => sub { Hash::Merge::_merge_hashes( $_[0], $_[1] ) },
		},



( run in 0.445 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )