Completed
Pull Request — master (#53)
by
unknown
01:20
created

CapakeyRestGateway.get_kadastrale_afdeling_by_id()   B

Complexity

Conditions 3

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
dl 0
loc 29
rs 8.8571
1
# -*- coding: utf-8 -*-
2
'''
3
This module contains an opionated gateway for the capakey webservice.
4
5
.. versionadded:: 0.2.0
6
'''
7
8
from __future__ import unicode_literals
9
import six
10
11
import logging
12
log = logging.getLogger(__name__)
13
14
from crabpy.client import capakey_request
15
16
from suds import WebFault
17
18
from crabpy.gateway.exception import (
19
    GatewayRuntimeException,
20
    GatewayAuthenticationException,
21
    GatewayResourceNotFoundException
22
)
23
24
from dogpile.cache import make_region
25
26
import requests
27
28
29
def capakey_gateway_request(client, method, *args):
30
    '''
31
    Utility function that helps making requests to the CAPAKEY service.
32
33
    This is a specialised version of :func:`crabpy.client.capakey_request` that
34
    allows adding extra functionality like general error handling for the
35
    calls made by the gateway.
36
37
    :param client: A :class:`suds.client.Client` for the CAPAKEY service.
38
    :param string action: Which method to call, eg. `ListAdmGemeenten`.
39
    :returns: Result of the SOAP call.
40
    '''
41
    try:
42
        return capakey_request(client, method, *args)
43
    except WebFault as wf:
44
        if wf.fault['faultcode'] == 'q0:FailedAuthentication':
45
            err = GatewayAuthenticationException(
46
                'Could not authenticate with capakey service. Message from server:\n%s' % wf.fault['faultstring'],
47
                wf
48
            )
49
        else:
50
            err = GatewayRuntimeException(
51
                'Could not execute request. Message from server:\n%s' % wf.fault['faultstring'],
52
                wf
53
            )
54
        raise err
55
56
57
class CapakeyGateway(object):
58
    '''
59
    A gateway to the capakey webservice.
60
    '''
61
62
    caches = {}
63
64 View Code Duplication
    def __init__(self, client, **kwargs):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
65
        self.client = client
66
        cache_regions = ['permanent', 'long', 'short']
67
        for cr in cache_regions:
68
            self.caches[cr] = make_region(key_mangler=str)
69
        if 'cache_config' in kwargs:
70
            for cr in cache_regions:
71
                if ('%s.backend' % cr) in kwargs['cache_config']:
72
                    log.debug('Configuring %s region on CapakeyGateway', cr)
73
                    self.caches[cr].configure_from_config(
74
                        kwargs['cache_config'],
75
                        '%s.' % cr
76
                    )
77
78
    def list_gemeenten(self, sort=1):
79
        '''
80
        List all `gemeenten` in Vlaanderen.
81
82
        :param integer sort: What field to sort on.
83
        :rtype: A :class:`list` of :class:`Gemeente`.
84
        '''
85
        def creator():
86
            res = capakey_gateway_request(
87
                self.client, 'ListAdmGemeenten', sort
88
            )
89
            return [
90
                Gemeente(r.Niscode, r.AdmGemeentenaam)
91
                for r in res.AdmGemeenteItem
92
            ]
93
        if self.caches['permanent'].is_configured:
94
            key = 'ListAdmGemeenten#%s' % sort
95
            gemeente = self.caches['permanent'].get_or_create(key, creator)
96
        else:
97
            gemeente = creator()
98
        for g in gemeente:
99
            g.set_gateway(self)
100 View Code Duplication
        return gemeente
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
101
102
    def get_gemeente_by_id(self, id):
103
        '''
104
        Retrieve a `gemeente` by id (the NIScode).
105
106
        :rtype: :class:`Gemeente`
107
        '''
108
        def creator():
109
            try:
110
                res = capakey_gateway_request(
111
                    self.client, 'GetAdmGemeenteByNiscode', id
112
                )
113
            except GatewayRuntimeException:
114
                raise GatewayResourceNotFoundException()
115
            return Gemeente(
116
                res.Niscode,
117
                res.AdmGemeentenaam,
118
                (res.CenterX, res.CenterY),
119
                (res.MinimumX, res.MinimumY, res.MaximumX, res.MaximumY)
120
            )
121
        if self.caches['long'].is_configured:
122
            key = 'GetAdmGemeenteByNiscode#%s' % id
123
            gemeente = self.caches['long'].get_or_create(key, creator)
124
        else:
125
            gemeente = creator()
126
        gemeente.set_gateway(self)
127
        return gemeente
128
129
    def list_kadastrale_afdelingen(self, sort=1):
130
        '''
131
        List all `kadastrale afdelingen` in Flanders.
132
133
        :param integer sort: Field to sort on.
134
        :rtype: A :class:`list` of :class:`Afdeling`.
135
        '''
136
        def creator():
137
            res = capakey_gateway_request(
138
                self.client, 'ListKadAfdelingen', sort
139
            )
140
            return [
141
                Afdeling(
142
                    id=r.KadAfdelingcode,
143
                    naam=r.KadAfdelingnaam,
144
                    gemeente=Gemeente(r.Niscode)
145
                ) for r in res.KadAfdelingItem]
146
        if self.caches['permanent'].is_configured:
147
            key = 'ListKadAfdelingen#%s' % sort
148
            afdelingen = self.caches['permanent'].get_or_create(key, creator)
149
        else:
150
            afdelingen = creator()
151
        for a in afdelingen:
152
            a.set_gateway(self)
153
        return afdelingen
154
155
    def list_kadastrale_afdelingen_by_gemeente(self, gemeente, sort=1):
156
        '''
157
        List all `kadastrale afdelingen` in a `gemeente`.
158
159
        :param gemeente: The :class:`Gemeente` for which the \
160
            `afdelingen` are wanted.
161
        :param integer sort: Field to sort on.
162
        :rtype: A :class:`list` of :class:`Afdeling`.
163
        '''
164
        try:
165
            gid = gemeente.id
166
        except AttributeError:
167
            gid = gemeente
168
            gemeente = self.get_gemeente_by_id(gid)
169
        gemeente.clear_gateway()
170
171
        def creator():
172
            res = capakey_gateway_request(
173
                self.client, 'ListKadAfdelingenByNiscode', gid, sort
174
            )
175
            try:
176
                return [
177
                    Afdeling(
178
                        id=r.KadAfdelingcode,
179
                        naam=r.KadAfdelingnaam,
180
                        gemeente=gemeente
181
                    ) for r in res.KadAfdelingItem]
182
            except AttributeError:
183
                # Handle bad error handling on the CAPAKEY side
184
                return []
185
        if self.caches['permanent'].is_configured:
186
            key = 'ListKadAfdelingenByNiscode#%s#%s' % (gid, sort)
187
            afdelingen = self.caches['permanent'].get_or_create(key, creator)
188
        else:
189
            afdelingen = creator()
190
        for a in afdelingen:
191
            a.set_gateway(self)
192
        return afdelingen
193
194
    def get_kadastrale_afdeling_by_id(self, id):
195
        '''
196
        Retrieve a 'kadastrale afdeling' by id.
197
198
        :param id: An id of a `kadastrale afdeling`.
199
        :rtype: A :class:`Afdeling`.
200
        '''
201
        def creator():
202
            try:
203
                res = capakey_gateway_request(
204
                    self.client, 'GetKadAfdelingByKadAfdelingcode', id
205
                )
206
            except GatewayRuntimeException:
207
                raise GatewayResourceNotFoundException()
208
            return Afdeling(
209
                id=res.KadAfdelingcode,
210
                naam=res.KadAfdelingnaam,
211
                gemeente=Gemeente(res.Niscode, res.AdmGemeentenaam),
212
                centroid=(res.CenterX, res.CenterY),
213
                bounding_box=(
214
                    res.MinimumX, res.MinimumY, res.MaximumX, res.MaximumY
215
                )
216
            )
217
        if self.caches['long'].is_configured:
218
            key = 'GetKadAfdelingByKadAfdelingcode#%s' % id
219
            afdeling = self.caches['long'].get_or_create(key, creator)
220
        else:
221
            afdeling = creator()
222
        afdeling.set_gateway(self)
223 View Code Duplication
        return afdeling
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
224
225
    def list_secties_by_afdeling(self, afdeling):
226
        '''
227
        List all `secties` in a `kadastrale afdeling`.
228
229
        :param afdeling: The :class:`Afdeling` for which the `secties` are \
230
            wanted. Can also be the id of and `afdeling`.
231
        :rtype: A :class:`list` of `Sectie`.
232
        '''
233
        try:
234
            aid = afdeling.id
235
        except AttributeError:
236
            aid = afdeling
237
            afdeling = self.get_kadastrale_afdeling_by_id(aid)
238
        afdeling.clear_gateway()
239
240
        def creator():
241
            res = capakey_gateway_request(
242
                self.client, 'ListKadSectiesByKadAfdelingcode', aid
243
            )
244
            try:
245
                return [
246
                    Sectie(
247
                        r.KadSectiecode,
248
                        afdeling
249
                    ) for r in res.KadSectieItem
250
                ]
251
            except AttributeError:
252
                # Handle bad error handling on the CAPAKEY side
253
                return []
254
        if self.caches['long'].is_configured:
255
            key = 'ListKadSectiesByKadAfdelingcode#%s' % aid
256
            secties = self.caches['long'].get_or_create(key, creator)
257
        else:
258
            secties = creator()
259
        for s in secties:
260
            s.set_gateway(self)
261
        return secties
262
263
    def get_sectie_by_id_and_afdeling(self, id, afdeling):
264
        '''
265
        Get a `sectie`.
266
267
        :param id: An id of a sectie. eg. "A"
268
        :param afdeling: The :class:`Afdeling` for in which the `sectie` can \
269
            be found. Can also be the id of and `afdeling`.
270
        :rtype: A :class:`Sectie`.
271
        '''
272
        try:
273
            aid = afdeling.id
274
        except AttributeError:
275
            aid = afdeling
276
            afdeling = self.get_kadastrale_afdeling_by_id(aid)
277
        afdeling.clear_gateway()
278
279
        def creator():
280
            try:
281
                res = capakey_gateway_request(
282
                    self.client, 'GetKadSectieByKadSectiecode', aid, id
283
                )
284
            except GatewayRuntimeException:
285
                raise GatewayResourceNotFoundException()
286
            return Sectie(
287
                res.KadSectiecode,
288
                afdeling,
289
                (res.CenterX, res.CenterY),
290
                (res.MinimumX, res.MinimumY, res.MaximumX, res.MaximumY),
291
            )
292
        if self.caches['long'].is_configured:
293
            key = 'GetKadSectieByKadSectiecode#%s#%s' % (aid, id)
294
            sectie = self.caches['long'].get_or_create(key, creator)
295
        else:
296
            sectie = creator()
297
        sectie.set_gateway(self)
298
        return sectie
299
300
    def list_percelen_by_sectie(self, sectie, sort=1):
301
        '''
302
        List all percelen in a `sectie`.
303
304
        :param sectie: The :class:`Sectie` for which the percelen are wanted.
305
        :param integer sort: Field to sort on.
306
        :rtype: A :class:`list` of :class:`Perceel`.
307
        '''
308
        sectie.clear_gateway()
309
310
        def creator():
311
            res = capakey_gateway_request(
312
                self.client, 'ListKadPerceelsnummersByKadSectiecode',
313
                sectie.afdeling.id, sectie.id, sort
314
            )
315
            try:
316
                return [
317
                    Perceel(
318
                        r.KadPerceelsnummer,
319
                        sectie,
320
                        r.CaPaKey,
321
                        r.PERCID,
322
                    ) for r in res.KadPerceelsnummerItem
323
                ]
324
            except AttributeError:
325
                # Handle bad error handling on the CAPAKEY side
326
                return []
327
        if self.caches['short'].is_configured:
328
            key = 'ListKadPerceelsnummersByKadSectiecode#%s#%s#%s' % (sectie.afdeling.id, sectie.id, sort)
329
            percelen = self.caches['short'].get_or_create(key, creator)
330
        else:
331
            percelen = creator()
332
        for p in percelen:
333
            p.set_gateway(self)
334 View Code Duplication
        return percelen
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
335
336
    def get_perceel_by_id_and_sectie(self, id, sectie):
337
        '''
338
        Get a `perceel`.
339
340
        :param id: An id for a `perceel`.
341
        :param sectie: The :class:`Sectie` that contains the perceel.
342
        :rtype: :class:`Perceel`
343
        '''
344
        sectie.clear_gateway()
345
346
        def creator():
347
            try:
348
                res = capakey_gateway_request(
349
                    self.client, 'GetKadPerceelsnummerByKadPerceelsnummer',
350
                    sectie.afdeling.id, sectie.id, id
351
                )
352
            except GatewayRuntimeException:
353
                raise GatewayResourceNotFoundException()
354
            return Perceel(
355
                res.KadPerceelsnummer,
356
                sectie,
357
                res.CaPaKey,
358
                res.PERCID,
359
                res.CaPaTy,
360
                res.CaShKey,
361
                (res.CenterX, res.CenterY),
362
                (res.MinimumX, res.MinimumY, res.MaximumX, res.MaximumY)
363
            )
364
        if self.caches['short'].is_configured:
365
            key = 'GetKadPerceelsnummerByKadPerceelsnummer#%s#%s#%s' % (sectie.afdeling.id, sectie.id, id)
366
            perceel = self.caches['short'].get_or_create(key, creator)
367
        else:
368
            perceel = creator()
369
        perceel.set_gateway(self)
370 View Code Duplication
        return perceel
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
371
372
    def get_perceel_by_capakey(self, capakey):
373
        '''
374
        Get a `perceel`.
375
376
        :param capakey: An capakey for a `perceel`.
377
        :rtype: :class:`Perceel`
378
        '''
379
        def creator():
380
            try:
381
                res = capakey_gateway_request(
382
                    self.client, 'GetKadPerceelsnummerByCaPaKey', capakey
383
                )
384
            except GatewayRuntimeException:
385
                raise GatewayResourceNotFoundException()
386
            return Perceel(
387
                res.KadPerceelsnummer,
388
                Sectie(res.KadSectiecode, Afdeling(res.KadAfdelingcode)),
389
                res.CaPaKey,
390
                res.PERCID,
391
                res.CaPaTy,
392
                res.CaShKey,
393
                (res.CenterX, res.CenterY),
394
                (res.MinimumX, res.MinimumY, res.MaximumX, res.MaximumY)
395
            )
396
        if self.caches['short'].is_configured:
397
            key = 'GetKadPerceelsnummerByCaPaKey#%s' % capakey
398
            perceel = self.caches['short'].get_or_create(key, creator)
399
        else:
400
            perceel = creator()
401
        perceel.set_gateway(self)
402
        return perceel
403
404
    def get_perceel_by_percid(self, percid):
405
        '''
406
        Get a `perceel`.
407
408
        :param percid: A percid for a `perceel`.
409
        :rtype: :class:`Perceel`
410
        '''
411
        def creator():
412
            try:
413
                res = capakey_gateway_request(
414
                    self.client, 'GetKadPerceelsnummerByPERCID', percid
415
                )
416
            except GatewayRuntimeException:
417
                raise GatewayResourceNotFoundException()
418
            return Perceel(
419
                res.KadPerceelsnummer,
420
                Sectie(res.KadSectiecode, Afdeling(res.KadAfdelingcode)),
421
                res.CaPaKey,
422
                res.PERCID,
423
                res.CaPaTy,
424
                res.CaShKey,
425
                (res.CenterX, res.CenterY),
426
                (res.MinimumX, res.MinimumY, res.MaximumX, res.MaximumY)
427
            )
428
        if self.caches['short'].is_configured:
429
            key = 'GetKadPerceelsnummerByPERCID#%s' % percid
430
            perceel = self.caches['short'].get_or_create(key, creator)
431
        else:
432
            perceel = creator()
433
        perceel.set_gateway(self)
434
        return perceel
435
436
437
def capakey_rest_gateway_request(url, headers={}, params={}):
438
    try:
439
        res = requests.get(url, headers=headers, params=params)
440
        res.raise_for_status()
441
        return res
442
    except requests.ConnectionError as ce:
443
        raise GatewayRuntimeException(
444
            'Could not execute request due to connection problems:\n%s' % repr(ce),
445
            ce
446
        )
447
    except requests.HTTPError as he:
448
        raise GatewayResourceNotFoundException()
449
    except requests.RequestException as re:
450
        raise GatewayRuntimeException(
451
            'Could not execute request due to:\n%s' % repr(re),
452
            re
453
        )
454
455
456
class CapakeyRestGateway(object):
457
    '''
458
    A REST gateway to the capakey webservice.
459
    '''
460
461
    caches = {}
462
463 View Code Duplication
    def __init__(self, **kwargs):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
464
        self.base_url = kwargs.get(
465
            'base_url',
466
            'https://geoservices.beta.informatievlaanderen.be/capakey/api/v0.1'
467
        )
468
        self.base_headers = {
469
            'Accept': 'application/json'
470
        }
471
        cache_regions = ['permanent', 'long', 'short']
472
        for cr in cache_regions:
473
            self.caches[cr] = make_region(key_mangler=str)
474
        if 'cache_config' in kwargs:
475
            for cr in cache_regions:
476
                if ('%s.backend' % cr) in kwargs['cache_config']:
477
                    log.debug('Configuring %s region on CapakeyRestGateway', cr)
478
                    self.caches[cr].configure_from_config(
479
                        kwargs['cache_config'],
480
                        '%s.' % cr
481
                    )
482
483 View Code Duplication
    def list_gemeenten(self, sort=1):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
484
        '''
485
        List all `gemeenten` in Vlaanderen.
486
487
        :param integer sort: What field to sort on.
488
        :rtype: A :class:`list` of :class:`Gemeente`.
489
        '''
490
        def creator():
491
            url = self.base_url + '/municipality'
492
            h = self.base_headers
493
            p = {
494
                'orderbyCode': sort == 1
495
            }
496
            res = capakey_rest_gateway_request(url, h, p).json()
497
            return [
498
                Gemeente(r['municipalityCode'], r['municipalityName'])
499
                for r in res['municipalities']
500
            ]
501
        if self.caches['permanent'].is_configured:
502
            key = 'list_gemeenten_rest#%s' % sort
503
            gemeente = self.caches['permanent'].get_or_create(key, creator)
504
        else:
505
            gemeente = creator()
506
        for g in gemeente:
507
            g.set_gateway(self)
508
        return gemeente
509
510
    def get_gemeente_by_id(self, id):
511
        '''
512
        Retrieve a `gemeente` by id (the NIScode).
513
514
        :rtype: :class:`Gemeente`
515
        '''
516
        def creator():
517
            url = self.base_url + '/municipality/%s' % id
518
            h = self.base_headers
519
            p = {
520
                'geometry': 'bbox',
521
                'srs': 31370
522
            }
523
            res = capakey_rest_gateway_request(url, h, p).json()
524
            return Gemeente(
525
                res['municipalityCode'],
526
                res['municipalityName'],
527
                res['geometry']['center'],
528
                res['geometry']['boundingBox']
529
            )
530
        if self.caches['long'].is_configured:
531
            key = 'get_gemeente_by_id_rest#%s' % id
532
            gemeente = self.caches['long'].get_or_create(key, creator)
533
        else:
534
            gemeente = creator()
535
        gemeente.set_gateway(self)
536
        return gemeente
537
538
    def list_kadastrale_afdelingen(self):
539
        '''
540
        List all `kadastrale afdelingen` in Flanders.
541
542
        :param integer sort: Field to sort on.
543
        :rtype: A :class:`list` of :class:`Afdeling`.
544
        '''
545
        def creator():
546
            gemeentes = self.list_gemeenten()
547
            res = []
548
            for g in gemeentes:
549
                res += self.list_kadastrale_afdelingen_by_gemeente(g)
550
            return res
551
        if self.caches['permanent'].is_configured:
552
            key = 'list_afdelingen_rest'
553
            afdelingen = self.caches['permanent'].get_or_create(key, creator)
554
        else:
555
            afdelingen = creator()
556
        return afdelingen
557
558
    def list_kadastrale_afdelingen_by_gemeente(self, gemeente, sort=1):
559
        '''
560
        List all `kadastrale afdelingen` in a `gemeente`.
561
562
        :param gemeente: The :class:`Gemeente` for which the \
563
            `afdelingen` are wanted.
564
        :param integer sort: Field to sort on.
565
        :rtype: A :class:`list` of :class:`Afdeling`.
566
        '''
567
        try:
568
            gid = gemeente.id
569
        except AttributeError:
570
            gid = gemeente
571
            gemeente = self.get_gemeente_by_id(gid)
572
        gemeente.clear_gateway()
573
574
        def creator():
575
            url = self.base_url + '/municipality/%s/department' % gid
576
            h = self.base_headers
577
            p = {
578
                'orderbyCode': sort == 1
579
            }
580
            res = capakey_rest_gateway_request(url, h, p).json()
581
            return [
582
                Afdeling(
583
                    id=r['departmentCode'],
584
                    naam=r['departmentName'],
585
                    gemeente=gemeente
586
                ) for r in res['departments']]
587
        if self.caches['permanent'].is_configured:
588
            key = 'list_kadastrale_afdelingen_by_gemeente_rest#%s#%s' % (gid, sort)
589
            afdelingen = self.caches['permanent'].get_or_create(key, creator)
590
        else:
591
            afdelingen = creator()
592
        for a in afdelingen:
593
            a.set_gateway(self)
594
        return afdelingen
595
596
    def get_kadastrale_afdeling_by_id(self, aid):
597
        '''
598
        Retrieve a 'kadastrale afdeling' by id.
599
600
        :param aid: An id of a `kadastrale afdeling`.
601
        :rtype: A :class:`Afdeling`.
602
        '''
603
        def creator():
604
            url = self.base_url + '/department/%s' % (aid)
605
            h = self.base_headers
606
            p = {
607
                'geometry': 'bbox',
608
                'srs': 31370
609
            }
610
            res = capakey_rest_gateway_request(url, h, p).json()
611
            return Afdeling(
612
                id=res['departmentCode'],
613
                naam=res['departmentName'],
614
                gemeente=Gemeente(res['municipalityCode'], res['municipalityName']),
615
                centroid=res['geometry']['center'],
616
                bounding_box=res['geometry']['boundingBox']
617
            )
618
        if self.caches['long'].is_configured:
619
            key = 'get_kadastrale_afdeling_by_id_rest#%s' % id
620
            afdeling = self.caches['long'].get_or_create(key, creator)
621
        else:
622
            afdeling = creator()
623
        afdeling.set_gateway(self)
624
        return afdeling
625
626
    def list_secties_by_afdeling(self, afdeling):
627
        '''
628
        List all `secties` in a `kadastrale afdeling`.
629
630
        :param afdeling: The :class:`Afdeling` for which the `secties` are \
631
            wanted. Can also be the id of and `afdeling`.
632
        :rtype: A :class:`list` of `Sectie`.
633
        '''
634
        try:
635
            aid = afdeling.id
636
        except AttributeError:
637
            aid = afdeling
638
            afdeling = self.get_kadastrale_afdeling_by_id(aid)
639
        afdeling.clear_gateway()
640
641
        def creator():
642
            url = self.base_url + '/municipality/%s/department/%s/section' % (afdeling.gemeente.id, afdeling.id)
643
            h = self.base_headers
644
            p = {
645
                'geometry': 'bbox',
646
                'srs': 31370
647
            }
648
            res = capakey_rest_gateway_request(url, h, p).json()
649
            return [
650
                Sectie(
651
                    r['sectionCode'],
652
                    afdeling
653
                ) for r in res['sections']
654
            ]
655
        if self.caches['long'].is_configured:
656
            key = 'list_secties_by_afdeling_rest#%s' % aid
657
            secties = self.caches['long'].get_or_create(key, creator)
658
        else:
659
            secties = creator()
660
        for s in secties:
661
            s.set_gateway(self)
662
        return secties
663
664
    def get_sectie_by_id_and_afdeling(self, id, afdeling):
665
        '''
666
        Get a `sectie`.
667
668
        :param id: An id of a sectie. eg. "A"
669
        :param afdeling: The :class:`Afdeling` for in which the `sectie` can \
670
            be found. Can also be the id of and `afdeling`.
671
        :rtype: A :class:`Sectie`.
672
        '''
673
        try:
674
            aid = afdeling.id
675
        except AttributeError:
676
            aid = afdeling
677
            afdeling = self.get_kadastrale_afdeling_by_id(aid)
678
        afdeling.clear_gateway()
679
680
        def creator():
681
            url = self.base_url + '/municipality/%s/department/%s/section/%s' % (afdeling.gemeente.id, afdeling.id, id)
682
            h = self.base_headers
683
            p = {
684
                'geometry': 'bbox',
685
                'srs': 31370
686
            }
687
            res = capakey_rest_gateway_request(url, h, p).json()
688
            return Sectie(
689
                res['sectionCode'],
690
                afdeling,
691
                res['geometry']['center'],
692
                res['geometry']['boundingBox'],
693
            )
694
        if self.caches['long'].is_configured:
695
            key = 'get_sectie_by_id_and_afdeling_rest#%s#%s' % (id, aid)
696
            sectie = self.caches['long'].get_or_create(key, creator)
697
        else:
698
            sectie = creator()
699
        sectie.set_gateway(self)
700
        return sectie
701
702
    def parse_percid(self, capakey):
703
        import re
704
        match = re.match(
705
            r"^([0-9]{5})([A-Z]{1})([0-9]{4})\/([0-9]{2})([A-Z\_]{1})([0-9]{3})$",
706
            capakey
707
        )
708
        if match:
709
            percid = match.group(1) + '_' + match.group(2) +\
710
                '_' + match.group(3) + '_' + match.group(5) + '_' +\
711
                match.group(6) + '_' + match.group(4)
712
            return percid
713
        else:
714
            raise ValueError(
715
                "Invalid Capakey %s can't be parsed" % capakey
716
            )
717
718
    def parse_capakey(self, percid):
719
        import re
720
        match = re.match(
721
            r"^([0-9]{5})_([A-Z]{1})_([0-9]{4})_([A-Z\_]{1})_([0-9]{3})_([0-9]{2})$",
722
            percid
723
        )
724
        if match:
725
            capakey = match.group(1) + match.group(2) +\
726
                match.group(3) + '/' + match.group(5) + '_' +\
727
                match.group(6) + '_' + match.group(4)
728
            return capakey
729
        else:
730
            raise ValueError(
731
                "Invalid percid %s can't be parsed" % percid
732
            )
733
734
    def list_percelen_by_sectie(self, sectie, sort=1):
735
        '''
736
        List all percelen in a `sectie`.
737
738
        :param sectie: The :class:`Sectie` for which the percelen are wanted.
739
        :param integer sort: Field to sort on.
740
        :rtype: A :class:`list` of :class:`Perceel`.
741
        '''
742
        sid = sectie.id
743
        aid = sectie.afdeling.id
744
        gid = sectie.afdeling.gemeente.id
745
        sectie.clear_gateway()
746
        def creator():
747
            url = self.base_url + '/municipality/%s/department/%s/section/%s/parcel' % (gid, aid, sid)
748
            h = self.base_headers
749
            res = capakey_rest_gateway_request(url, h).json()
750
            return [
751
                Perceel(
752
                    r['perceelnummer'],
753
                    sectie,
754
                    r['capakey'],
755
                    self.parse_percid(r['capakey']),
756
                ) for r in res['parcels']
757
            ]
758
        if self.caches['short'].is_configured:
759
            key = 'list_percelen_by_sectie_rest#%s#%s#%s' % (gid, aid, sid)
760
            percelen = self.caches['short'].get_or_create(key, creator)
761
        else:
762
            percelen = creator()
763
        for p in percelen:
764
            p.set_gateway(self)
765
        return percelen
766
767
    def get_perceel_by_id_and_sectie(self, id, sectie):
768
        '''
769
        Get a `perceel`.
770
771
        :param id: An id for a `perceel`.
772
        :param sectie: The :class:`Sectie` that contains the perceel.
773
        :rtype: :class:`Perceel`
774
        '''
775
        sid = sectie.id
776
        aid = sectie.afdeling.id
777
        gid = sectie.afdeling.gemeente.id
778
        sectie.clear_gateway()
779
        def creator():
780
            url = self.base_url + '/municipality/%s/department/%s/section/%s/parcel/%s' % (gid, aid, sid, id)
781
            h = self.base_headers
782
            p = {
783
                'geometry': 'bbox',
784
                'srs': 31370
785
            }
786
            res = capakey_rest_gateway_request(url, p, h).json()
787
            return Perceel(
788
                res['perceelnummer'],
789
                sectie,
790
                res['capakey'],
791
                Perceel.get_percid_from_capakey(res['capakey']),
792
                None,
793
                None,
794
                res['geometry']['center'],
795
                res['geometry']['boundingBox']
796
            )
797
        if self.caches['short'].is_configured:
798
            key = 'get_perceel_by_id_and_sectie_rest#%s#%s#%s' % (id, sectie.id, sectie.afdeling.id)
799
            perceel = self.caches['short'].get_or_create(key, creator)
800
        else:
801
            perceel = creator()
802
        perceel.set_gateway(self)
803
        return perceel
804
805
    def get_perceel_by_capakey(self, capakey):
806
        '''
807
        Get a `perceel`.
808
809
        :param capakey: An capakey for a `perceel`.
810
        :rtype: :class:`Perceel`
811
        '''
812
        def creator():
813
            url = self.base_url + '/parcel/%s' % capakey
814
            h = self.base_headers
815
            p = {
816
                'geometry': 'bbox',
817
                'srs': 31370
818
            }
819
            res = capakey_rest_gateway_request(url, p, h).json()
820
            return Perceel(
821
                res['perceelnummer'],
822
                Sectie(
823
                    res['sectionCode'],
824
                    Afdeling(
825
                        res['departmentCode'],
826
                        res['departmentName'],
827
                        Gemeente(res['municipalityCode'], res['municipalityName'])
828
                    )
829
                ),
830
                res['capakey'],
831
                Perceel.get_percid_from_capakey(res['capakey']),
832
                None,
833
                None,
834
                res['geometry']['center'],
835
                res['geometry']['boundingBox']
836
            )
837
        if self.caches['short'].is_configured:
838
            key = 'get_perceel_by_capakey_rest#%s' % capakey
839
            perceel = self.caches['short'].get_or_create(key, creator)
840
        else:
841
            perceel = creator()
842
        perceel.set_gateway(self)
843
        return perceel
844
845
    def get_perceel_by_percid(self, percid):
846
        '''
847
        Get a `perceel`.
848
849
        :param percid: A percid for a `perceel`.
850
        :rtype: :class:`Perceel`
851
        '''
852
        return self.get_perceel_by_capakey(
853
            Perceel.get_capakey_from_percid(percid)
854
        )
855
856
857
class GatewayObject(object):
858
    '''
859
    Abstract class for all objects being returned from the Gateway.
860
    '''
861
862
    gateway = None
863
    '''
864
    The :class:`crabpy.gateway.capakey.CapakeyGateway` to use when making
865
    further calls to the Capakey service.
866
    '''
867
868
    def __init__(self, **kwargs):
869
        if 'gateway' in kwargs:
870
            self.set_gateway(kwargs['gateway'])
871
872
    def set_gateway(self, gateway):
873
        '''
874
        :param crabpy.gateway.capakey.CapakeyGateway gateway: Gateway to use.
875
        '''
876
        self.gateway = gateway
877
878
    def clear_gateway(self):
879
        '''
880
        Clear the currently set CapakeyGateway.
881
        '''
882
        self.gateway = None
883
884
    def check_gateway(self):
885
        '''
886
        Check to see if a gateway was set on this object.
887
        '''
888
        if not self.gateway:
889
            raise RuntimeError("There's no Gateway I can use")
890
891
    if six.PY2:
892
        def __str__(self):
893
            return self.__unicode__().encode('utf-8')
894
    else:
895
        def __str__(self):
896
            return self.__unicode__()
897
898
899
def check_lazy_load_gemeente(f):
900
    '''
901
    Decorator function to lazy load a :class:`Gemeente`.
902
    '''
903
    def wrapper(self):
904
        gemeente = self
905
        if (getattr(gemeente, '_%s' % f.__name__, None) is None):
906
            log.debug('Lazy loading Gemeente %d', gemeente.id)
907
            gemeente.check_gateway()
908
            g = gemeente.gateway.get_gemeente_by_id(gemeente.id)
909
            gemeente._naam = g._naam
910
            gemeente._centroid = g._centroid
911
            gemeente._bounding_box = g._bounding_box
912
        return f(self)
913
    return wrapper
914
915
916
class Gemeente(GatewayObject):
917
    '''
918
    The smallest administrative unit in Belgium.
919
    '''
920
921
    def __init__(
922
            self, id, naam=None,
923
            centroid=None, bounding_box=None,
924
            **kwargs
925
    ):
926
        self.id = int(id)
927
        self._naam = naam
928
        self._centroid = centroid
929
        self._bounding_box = bounding_box
930
        super(Gemeente, self).__init__(**kwargs)
931
932
    @property
933
    @check_lazy_load_gemeente
934
    def naam(self):
935
        return self._naam
936
937
    @property
938
    @check_lazy_load_gemeente
939
    def centroid(self):
940
        return self._centroid
941
942
    @property
943
    @check_lazy_load_gemeente
944
    def bounding_box(self):
945
        return self._bounding_box
946
947
    @property
948
    def afdelingen(self):
949
        self.check_gateway()
950
        return self.gateway.list_kadastrale_afdelingen_by_gemeente(self)
951
952
    def __unicode__(self):
953
        return '%s (%s)' % (self.naam, self.id)
954
955
    def __repr__(self):
956
        return "Gemeente(%s, '%s')" % (self.id, self.naam)
957
958
959
def check_lazy_load_afdeling(f):
960
    '''
961
    Decorator function to lazy load a :class:`Afdeling`.
962
    '''
963
    def wrapper(self):
964
        afdeling = self
965
        if (getattr(afdeling, '_%s' % f.__name__, None) is None):
966
            log.debug('Lazy loading Afdeling %d', afdeling.id)
967
            afdeling.check_gateway()
968
            a = afdeling.gateway.get_kadastrale_afdeling_by_id(afdeling.id)
969
            afdeling._naam = a._naam
970
            afdeling._gemeente = a._gemeente
971
            afdeling._centroid = a._centroid
972
            afdeling._bounding_box = a._bounding_box
973
        return f(self)
974 View Code Duplication
    return wrapper
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
975
976
977
class Afdeling(GatewayObject):
978
    '''
979
    A Cadastral Division of a :class:`Gemeente`.
980
    '''
981
982
    def __init__(
983
        self, id, naam=None, gemeente=None,
984
        centroid=None, bounding_box=None,
985
        **kwargs
986
    ):
987
        self.id = int(id)
988
        self._naam = naam
989
        self._gemeente = gemeente
990
        self._centroid = centroid
991
        self._bounding_box = bounding_box
992
        super(Afdeling, self).__init__(**kwargs)
993
994
    def set_gateway(self, gateway):
995
        '''
996
        :param crabpy.gateway.capakey.CapakeyGateway gateway: Gateway to use.
997
        '''
998
        self.gateway = gateway
999
        if (self._gemeente is not None):
1000
            self._gemeente.set_gateway(gateway)
1001
1002
    def clear_gateway(self):
1003
        '''
1004
        Clear the currently set CapakeyGateway.
1005
        '''
1006
        self.gateway = None
1007
        if (self._gemeente is not None):
1008
            self._gemeente.clear_gateway()
1009
1010
    @property
1011
    @check_lazy_load_afdeling
1012
    def naam(self):
1013
        return self._naam
1014
1015
    @property
1016
    @check_lazy_load_afdeling
1017
    def gemeente(self):
1018
        return self._gemeente
1019
1020
    @property
1021
    @check_lazy_load_afdeling
1022
    def centroid(self):
1023
        return self._centroid
1024
1025
    @property
1026
    @check_lazy_load_afdeling
1027
    def bounding_box(self):
1028
        return self._bounding_box
1029
1030
    @property
1031
    def secties(self):
1032
        self.check_gateway()
1033
        return self.gateway.list_secties_by_afdeling(self)
1034
1035
    def __unicode__(self):
1036
        if self._naam is not None:
1037
            return '%s (%s)' % (self._naam, self.id)
1038
        else:
1039
            return 'Afdeling %s' % (self.id)
1040
1041
    def __repr__(self):
1042
        if self._naam is not None:
1043
            return "Afdeling(%s, '%s')" % (self.id, self._naam)
1044
        else:
1045
            return 'Afdeling(%s)' % (self.id)
1046
1047
1048
def check_lazy_load_sectie(f):
1049
    '''
1050
    Decorator function to lazy load a :class:`Sectie`.
1051
    '''
1052
    def wrapper(self):
1053
        sectie = self
1054
        if (getattr(sectie, '_%s' % f.__name__, None) is None):
1055
            log.debug('Lazy loading Sectie %s in Afdeling %d', sectie.id, sectie.afdeling.id)
1056
            sectie.check_gateway()
1057
            s = sectie.gateway.get_sectie_by_id_and_afdeling(
1058
                sectie.id, sectie.afdeling.id
1059
            )
1060
            sectie._centroid = s._centroid
1061
            sectie._bounding_box = s._bounding_box
1062
        return f(self)
1063 View Code Duplication
    return wrapper
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1064
1065
1066
class Sectie(GatewayObject):
1067
    '''
1068
    A subdivision of a :class:`Afdeling`.
1069
    '''
1070
1071
    def __init__(
1072
        self, id, afdeling,
1073
        centroid=None, bounding_box=None,
1074
        **kwargs
1075
    ):
1076
        self.id = id
1077
        self.afdeling = afdeling
1078
        self._centroid = centroid
1079
        self._bounding_box = bounding_box
1080
        super(Sectie, self).__init__(**kwargs)
1081
1082
    def set_gateway(self, gateway):
1083
        '''
1084
        :param crabpy.gateway.capakey.CapakeyGateway gateway: Gateway to use.
1085
        '''
1086
        self.gateway = gateway
1087
        self.afdeling.set_gateway(gateway)
1088
1089
    def clear_gateway(self):
1090
        '''
1091
        Clear the currently set CapakeyGateway.
1092
        '''
1093
        self.gateway = None
1094
        self.afdeling.clear_gateway()
1095
1096
    @property
1097
    @check_lazy_load_sectie
1098
    def centroid(self):
1099
        return self._centroid
1100
1101
    @property
1102
    @check_lazy_load_sectie
1103
    def bounding_box(self):
1104
        return self._bounding_box
1105
1106
    @property
1107
    def percelen(self):
1108
        self.check_gateway()
1109
        return self.gateway.list_percelen_by_sectie(self)
1110
1111
    def __unicode__(self):
1112
        return '%s, Sectie %s' % (self.afdeling, self.id)
1113
1114
    def __repr__(self):
1115
        return "Sectie('%s', %s)" % (self.id, repr(self.afdeling))
1116
1117
1118
def check_lazy_load_perceel(f):
1119
    '''
1120
    Decorator function to lazy load a :class:`Perceel`.
1121
    '''
1122
    def wrapper(self):
1123
        perceel = self
1124
        if (getattr(perceel, '_%s' % f.__name__, None) is None):
1125
            log.debug(
1126
                'Lazy loading Perceel %s in Sectie %s in Afdeling %d',
1127
                perceel.id,
1128
                perceel.sectie.id,
1129
                perceel.sectie.afdeling.id
1130
            )
1131
            perceel.check_gateway()
1132
            p = perceel.gateway.get_perceel_by_id_and_sectie(
1133 View Code Duplication
                perceel.id,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1134
                perceel.sectie
1135
            )
1136
            perceel._centroid = p._centroid
1137
            perceel._bounding_box = p._bounding_box
1138
            perceel._capatype = p._capatype
1139
            perceel._cashkey = p._cashkey
1140
        return f(self)
1141
    return wrapper
1142
1143
1144
class Perceel(GatewayObject):
1145
    '''
1146
    A Cadastral Parcel.
1147
    '''
1148
1149
    def __init__(
1150
        self, id, sectie, capakey, percid,
1151
        capatype=None, cashkey=None,
1152
        centroid=None, bounding_box=None,
1153
        **kwargs
1154
    ):
1155
        self.id = id
1156
        self.sectie = sectie
1157
        self.capakey = capakey
1158
        self.percid = percid
1159
        self._capatype = capatype
1160
        self._cashkey = cashkey
1161
        self._centroid = centroid
1162
        self._bounding_box = bounding_box
1163
        super(Perceel, self).__init__(**kwargs)
1164
        self._split_capakey()
1165
1166
    def set_gateway(self, gateway):
1167
        '''
1168
        :param crabpy.gateway.capakey.CapakeyGateway gateway: Gateway to use.
1169
        '''
1170
        self.gateway = gateway
1171
        self.sectie.set_gateway(gateway)
1172
1173
    def clear_gateway(self):
1174
        '''
1175
        Clear the currently set CapakeyGateway.
1176
        '''
1177
        self.gateway = None
1178
        self.sectie.clear_gateway()
1179
1180
    @staticmethod
1181
    def get_percid_from_capakey(capakey):
1182
        import re
1183
        match = re.match(
1184
            r"^([0-9]{5})([A-Z]{1})([0-9]{4})\/([0-9]{2})([A-Z\_]{1})([0-9]{3})$",
1185
            capakey
1186
        )
1187
        if match:
1188
            percid = match.group(1) + '_' + match.group(2) +\
1189
                '_' + match.group(3) + '_' + match.group(5) + '_' +\
1190
                match.group(6) + '_' + match.group(4)
1191
            return percid
1192
        else:
1193
            raise ValueError(
1194
                "Invalid Capakey %s can't be parsed" % capakey
1195
            )
1196
1197
    @staticmethod
1198
    def get_capakey_from_percid(percid):
1199
        import re
1200
        match = re.match(
1201
            r"^([0-9]{5})_([A-Z]{1})_([0-9]{4})_([A-Z\_]{1})_([0-9]{3})_([0-9]{2})$",
1202
            percid
1203
        )
1204
        if match:
1205
            capakey = match.group(1) + match.group(2) +\
1206
                match.group(3) + '/' + match.group(6) +\
1207
                match.group(4) + match.group(5)
1208
            return capakey
1209
        else:
1210
            raise ValueError(
1211
                "Invalid percid %s can't be parsed" % percid
1212
            )
1213
1214
    def _split_capakey(self):
1215
        '''
1216
        Split a capakey into more readable elements.
1217
1218
        Splits a capakey into it's grondnummer, bisnummer, exponent and macht.
1219
        '''
1220
        import re
1221
        match = re.match(
1222
            r"^[0-9]{5}[A-Z]{1}([0-9]{4})\/([0-9]{2})([A-Z\_]{1})([0-9]{3})$",
1223
            self.capakey
1224
        )
1225
        if match:
1226
            self.grondnummer = match.group(1)
1227
            self.bisnummer = match.group(2)
1228
            self.exponent = match.group(3)
1229
            self.macht = match.group(4)
1230
        else:
1231
            raise ValueError(
1232
                "Invalid Capakey %s can't be parsed" % self.capakey
1233
            )
1234
1235
    @property
1236
    @check_lazy_load_perceel
1237
    def centroid(self):
1238
        return self._centroid
1239
1240
    @property
1241
    @check_lazy_load_perceel
1242
    def bounding_box(self):
1243
        return self._bounding_box
1244
1245
    @property
1246
    @check_lazy_load_perceel
1247
    def capatype(self):
1248
        return self._capatype
1249
1250
    @property
1251
    @check_lazy_load_perceel
1252
    def cashkey(self):
1253
        return self._cashkey
1254
1255
    def __unicode__(self):
1256
        return self.capakey
1257
1258
    def __repr__(self):
1259
        return "Perceel('%s', %s, '%s', '%s')" % (
1260
            self.id, repr(self.sectie), self.capakey, self.percid
1261
        )
1262