PageRenderTime 26ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Zaaksysteem/Geo/BAG.pm

https://bitbucket.org/michielootjers/zaaksysteem-sprint2
Perl | 371 lines | 270 code | 93 blank | 8 comment | 15 complexity | f674cf131b8b9ff03b7eee45bff0e90a MD5 | raw file
  1. package Zaaksysteem::Geo::BAG;
  2. use Moose;
  3. use Zaaksysteem::Geo;
  4. use Data::Dumper;
  5. use constant SOURCE_TABLES => {
  6. nummeraanduiding => 'BagNummeraanduiding',
  7. openbareruimte => 'BagOpenbareruimte',
  8. woonplaats => 'BagWoonplaats'
  9. # Rest still unsupported
  10. };
  11. use constant ESSENTIAL_DATA => {
  12. BagNummeraanduiding => {
  13. parent => {
  14. table => 'BagOpenbareruimte',
  15. key => 'openbareruimte'
  16. },
  17. fields => {
  18. postcode => 'postcode',
  19. huisnummer => 'huisnummer',
  20. huisnummertoevoeging => 'huisnummertoevoeging',
  21. huisletter => 'huisletter',
  22. }
  23. },
  24. BagOpenbareruimte => {
  25. parent => {
  26. table => 'BagWoonplaats',
  27. key => 'woonplaats'
  28. },
  29. fields => {
  30. naam => 'straat',
  31. }
  32. },
  33. BagWoonplaats => {
  34. fields => {
  35. naam => 'woonplaats',
  36. }
  37. }
  38. };
  39. has 'apikey' => (
  40. 'is' => 'rw',
  41. 'lazy' => 1,
  42. 'default' => sub {
  43. my $self = shift;
  44. my $schema = $self->result_source->schema;
  45. #warn(Dumper($schema->default_resultset_attributes));
  46. return $schema
  47. ->default_resultset_attributes
  48. ->{config}
  49. ->{google_api_key}
  50. }
  51. );
  52. =head2 $component->geocode_term
  53. Return value: $geocode_address
  54. Generate a term for geocoding this location with a googlemaps or other
  55. geocoder.
  56. e.g:
  57. Nederland, Amsterdam, Donker Curtiusstraat 7
  58. Nederland, Amsterdam, Donker Curtiusstraat
  59. =cut
  60. sub geocode_term {}
  61. sub set_wsg_coordinates {
  62. my $self = shift;
  63. ### Only on component
  64. return unless UNIVERSAL::isa($self, 'DBIx::Class');
  65. return unless $self->can('coordinates_wsg');
  66. my $location = $self->get_wsg_location;
  67. if ($location) {
  68. $self->coordinates_wsg(
  69. join(',', @{ $location->{coordinates} })
  70. );
  71. $self->update;
  72. }
  73. }
  74. sub get_wsg_location {
  75. my $self = shift;
  76. my $term = shift;
  77. my $geocoder = Zaaksysteem::Geo->new(
  78. key => $self->apikey
  79. );
  80. my $location;
  81. eval {
  82. $geocoder->query($term || $self->geocode_term);
  83. $geocoder->geocode;
  84. if ($geocoder->success) {
  85. my $locationes = $geocoder->results;
  86. $location = shift( @{ $locationes });
  87. }
  88. };
  89. return $location;
  90. }
  91. =head2 $resultset->lookup_nearest_bag_object(geo_address)
  92. Return value: $BAG_ROW
  93. Given an arrayref of coordinates:
  94. $resultset->lookup_nearest_bag_object(
  95. 'Amsterdam, Donker Curtiusstraat 7'
  96. );
  97. Returns the nearest bag location
  98. =cut
  99. sub lookup_nearest_bag_object {
  100. my $self = shift;
  101. my $address = shift;
  102. return unless UNIVERSAL::isa($self, 'DBIx::Class::ResultSet');
  103. my $schema = $self->result_source->schema;
  104. my $location = $self->get_wsg_location($address);
  105. return unless $location;
  106. ### Find city
  107. my $city = $schema->resultset('BagWoonplaats')->search(
  108. {
  109. 'LOWER(naam)' => lc($location->city),
  110. }
  111. )->first or return;
  112. $address = lc($location->address);
  113. my ($streetname, $streetnumber) = $address =~ /^(.*?)\s+(\d.*)$/;
  114. unless ($streetname) {
  115. $streetname = $address;
  116. }
  117. my ($numberletter) = $streetnumber
  118. =~ /^\d+([a-z]+)/;
  119. my ($numbersuffix) = $streetnumber
  120. =~ /^\d+[a-z]+[\s-]+(.*)/i;
  121. $streetnumber =~ s/^(\d+).*/$1/;
  122. return unless $streetname;
  123. ### Find street
  124. my $street = $city->openbareruimten->search(
  125. {
  126. 'LOWER(naam)' => lc($streetname),
  127. }
  128. )->first or return;
  129. unless ($streetnumber) {
  130. return $street;
  131. }
  132. $address = $street->hoofdadressen->search(
  133. {
  134. 'huisnummer' => lc($streetnumber),
  135. }
  136. )->first or return $street;
  137. my $narrowaddress;
  138. unless (
  139. $numberletter &&
  140. (
  141. $narrowaddress = $address->search(
  142. {
  143. 'LOWER(huisletter)' => lc($numberletter)
  144. }
  145. )
  146. ) &&
  147. $narrowaddress->count
  148. ) {
  149. return $address;
  150. }
  151. my $suffixaddress;
  152. unless (
  153. $numbersuffix &&
  154. (
  155. $suffixaddress = $address->search(
  156. {
  157. 'LOWER(huisnummertoevoeging)' => lc($numbersuffix)
  158. }
  159. )
  160. ) &&
  161. $suffixaddress->count
  162. ) {
  163. return $narrowaddress->first;
  164. }
  165. return $suffixaddress->first;
  166. }
  167. =head2 $self->get_record_by_source_identifier($source_identifier)
  168. Return value: $DB_RECORD
  169. $self->get_record_by_source_identifier('nummeraanduiding-637372832372323')
  170. =cut
  171. sub get_record_by_source_identifier {
  172. my ($self, $source_identifier) = @_;
  173. die('Only call this method from a resultset object')
  174. unless UNIVERSAL::isa($self, 'DBIx::Class::ResultSet');
  175. my ($type, $id) = $source_identifier =~ /^(.+)\-(.+)$/;
  176. die "Need valid source_identifier (got: '$source_identifier')" unless $type && $id;
  177. die('Type: ' . $type . ' unsupported') unless SOURCE_TABLES()->{$type};
  178. return $self
  179. ->result_source
  180. ->schema->resultset(
  181. SOURCE_TABLES()->{$type}
  182. )->search(
  183. {
  184. identificatie => $id
  185. }
  186. )->first;
  187. }
  188. =head2 $self->get_address_data_by_source_identifier($source_identifier)
  189. Return value: \%ADDRESS_DATA
  190. print Dumper($self->get_address_data_by_source_identifier('nummeraanduiding-9876543218375842'));
  191. $VAR1 = {
  192. 'huisletter' => 'A',
  193. 'huisnummer' => 23,
  194. 'huisnummertoevoeging' => '1rec',
  195. 'postcode' => '1051JL',
  196. 'straat' => 'Donker Curtiusstraat',
  197. 'woonplaats' => 'Amsterdam'
  198. };
  199. =cut
  200. sub get_address_data_by_source_identifier {
  201. my ($self, $source_identifier) = @_;
  202. die('Only call this method from a resultset object')
  203. unless UNIVERSAL::isa($self, 'DBIx::Class::ResultSet');
  204. my $record = $self->get_record_by_source_identifier($source_identifier)
  205. or return;
  206. my $rv = {};
  207. while ($record) {
  208. my ($record_name) = ref($record) =~ /::([^:]+)$/;
  209. my $structure = ESSENTIAL_DATA()->{ $record_name };
  210. for my $field (keys %{ $structure->{fields} }) {
  211. my $value = $structure->{fields}->{ $field };
  212. $rv->{ $value } = $record->$field;
  213. }
  214. if (defined($structure->{parent}) && $structure->{parent}) {
  215. my $parent = $structure->{parent}->{key};
  216. $record = $record->$parent;
  217. next;
  218. }
  219. $record = undef;
  220. }
  221. return $rv;
  222. }
  223. =head2 $self->get_human_identifier_by_source_identifier($source_identifier [,\%options ])
  224. Return value: \%ADDRESS_DATA
  225. print $self->get_human_identifier_by_source_identifier('nummeraanduiding-9876543218375842');
  226. # Returns: "Donker Curtiusstraat 23A-1rec"
  227. Gives a human readable string of the given BAG source identifier, you can
  228. influence the output by using one of the identifiers below
  229. B<Options>
  230. =over 4
  231. =item prefix_with_city BOOLEAN
  232. print $self->get_human_identifier_by_source_identifier(
  233. 'nummeraanduiding-9876543218375842'
  234. {
  235. prefix_with_city => 1,
  236. }
  237. );
  238. # Returns: "Amsterdam - Donker Curtiusstraat 23A-1rec"
  239. Prefix the output with the city name
  240. =back
  241. =cut
  242. sub get_human_identifier_by_source_identifier {
  243. my ($self, $source_identifier, $options) = @_;
  244. $options ||= {};
  245. die('Only call this method from a resultset object')
  246. unless UNIVERSAL::isa($self, 'DBIx::Class::ResultSet');
  247. my $record = $self->get_record_by_source_identifier($source_identifier)
  248. or return;
  249. my ($bagtype) = $source_identifier =~ /^(\w+)-\d+/;
  250. if (lc($bagtype) eq 'nummeraanduiding') {
  251. return (
  252. (
  253. defined($options->{prefix_with_city}) &&
  254. $options->{prefix_with_city}
  255. ) ? $record->openbareruimte->woonplaats->naam . ' - '
  256. : ''
  257. ) .
  258. $record->openbareruimte->naam . ' ' . $record->nummeraanduiding;
  259. }
  260. if (lc($bagtype) eq 'pand') {
  261. return 'Bouwjaar: ' . $record->bouwjaar;
  262. }
  263. if (lc($bagtype) eq 'verblijfsobject') {
  264. return 'Oppervlakte: ' . $record->oppervlakte;
  265. }
  266. if (lc($bagtype) eq 'standplaats') {
  267. return '-';
  268. }
  269. if (lc($bagtype) eq 'ligplaats') {
  270. return '-';
  271. }
  272. if (lc($bagtype) eq 'openbareruimte') {
  273. return $record->naam;
  274. #return $record->woonplaats->naam . ' > ' . $record->naam;
  275. }
  276. return '';
  277. }
  278. 1;