summaryrefslogtreecommitdiff
path: root/chimere/utils.py
blob: d631fe7ddcf5088a9d4302446f1c09cd619faa68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2012  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# See the file COPYING for details.

"""
Utilitaries
"""

import urllib2
from lxml import etree

from django.core.exceptions import ObjectDoesNotExist

class ImportManager:
    u"""
    Generic class for specific importers
    """
    def __init__(self, importer_instance):
        self.importer_instance = importer_instance

    def get(self):
        pass

    def put(self):
        pass

class KMLManager(ImportManager):
    u"""
    KML importer/exporter
    The filtr argument has to be defined as a correct Xpath string pointing
    to Placemark nodes.
    A typical XPath string looks like:
    "//kml:Folder/kml:name[text()='Subcategory 1']/../kml:Placemark"
    """
    def __init__(self, importer_instance, ns=''):
        self.importer_instance = importer_instance
        self.ns = ns

    def get(self):
        u"""
        Get data from the source
        Return a tuple with:
        - number of new item ;
        - number of item updated ;
        - error detail on error
        """
        from models import Marker
        new_item, updated_item, msg = 0, 0, ''
        try:
            source = urllib2.urlopen(self.importer_instance.source_url)
        except ValueError:
            # assume it is a local file
            try:
                source = open(self.importer_instance.source_url)
            except IOError, msg:
                return (new_item, updated_item, msg)
        except urllib2.URLError as error:
            return (new_item, updated_item, error.reason)
        tree = etree.parse(source)
        # try to get default namespace
        if not self.ns:
            self.ns = tree.getroot().nsmap[None]
        for placemark in tree.xpath(self.importer_instance.filtr,
                                    namespaces={'kml':self.ns}):
            name, point, linestring = None, None, None
            pl_id = placemark.attrib.get('id')
            ns = '{%s}' % self.ns
            for item in placemark:
                if item.tag == ns + 'name':
                    name = item.text
                elif item.tag == ns + 'description':
                    description = item.text
                elif item.tag == ns + 'Point':
                    for coord in item:
                        if coord.tag == ns + 'coordinates':
                            x, y, z = coord.text.split(',')
                            point = 'SRID=4326;POINT(%s %s)' % (x, y)
            if point:
                dct = {'point':point,
                       'description':description,
                       'name':name,}
                m = None
                if pl_id:
                    dct_import = {
                        'import_key':pl_id,
                        'import_source':self.importer_instance.source_url}
                    try:
                        m = Marker.objects.get(**dct_import)
                        for k in dct:
                            setattr(m, k, dct[k])
                        m.save()
                        updated_item += 1
                    except ObjectDoesNotExist:
                        m = None
                        dct.update(dct_import)
                if not m:
                    dct['status'] = 'I'
                    m = Marker.objects.create(**dct)
                    new_item += 1
                m.categories.clear()
                for cat in self.importer_instance.categories.all():
                    m.categories.add(cat)
        return (new_item, updated_item, msg)

class OSMManager(ImportManager):
    pass