source: osmose-frontend/error.py

Last change on this file was f517d06, checked in by Frederic Rodrigo <fred.rodrigo@…>, 5 years ago

Replace 'error' by 'issue' in string deplayed at user

  • Property mode set to 100644
File size: 11.6 KB
Line 
1#! /usr/bin/env python
2#-*- coding: utf-8 -*-
3###########################################################################
4##                                                                       ##
5## Copyrights Etienne Chové <chove@crans.org> 2009                       ##
6##                                                                       ##
7## This program is free software: you can redistribute it and/or modify  ##
8## it under the terms of the GNU General Public License as published by  ##
9## the Free Software Foundation, either version 3 of the License, or     ##
10## (at your option) any later version.                                   ##
11##                                                                       ##
12## This program is distributed in the hope that it will be useful,       ##
13## but WITHOUT ANY WARRANTY; without even the implied warranty of        ##
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         ##
15## GNU General Public License for more details.                          ##
16##                                                                       ##
17## You should have received a copy of the GNU General Public License     ##
18## along with this program.  If not, see <http://www.gnu.org/licenses/>. ##
19##                                                                       ##
20###########################################################################
21
22from bottle import route, request, template, response, abort
23import StringIO, os, tempfile, copy
24
25from tools import osmose_common
26from tools import utils
27from tools import tag2link
28from tools import OsmSax
29
30t2l = tag2link.tag2link("tools/tag2link_sources.xml")
31
32
33def _get(db, err_id):
34    columns_marker = ["marker.item", "marker.source", "marker.class", "marker.elems", "marker.subclass",
35        "marker.lat", "marker.lon",
36        "dynpoi_class.title", "marker.subtitle", "dynpoi_class.timestamp"]
37    sql = "SELECT " + ",".join(columns_marker) + """
38    FROM
39        marker
40        JOIN dynpoi_class ON
41            marker.source = dynpoi_class.source AND
42            marker.class = dynpoi_class.class
43    WHERE
44        marker.id = %s
45    """
46    db.execute(sql, (err_id, ))
47    marker = db.fetchone()
48
49    if not marker:
50        abort(410, "Id is not present in database.")
51
52    columns_elements = ["elem_index", "data_type", "id", "tags", "username"]
53    sql = "SELECT " + ",".join(columns_elements) + """
54    FROM
55        marker_elem
56    WHERE
57        marker_id = %s
58    ORDER BY
59        elem_index
60    """
61    db.execute(sql, (err_id, ))
62    elements = db.fetchall()
63
64    columns_fix = ["diff_index", "elem_data_type", "elem_id", "tags_create", "tags_modify", "tags_delete"]
65    sql = "SELECT " + ",".join(columns_fix) + """
66    FROM
67        marker_fix
68    WHERE
69        marker_id = %s
70    ORDER BY
71        diff_index
72    """
73    db.execute(sql, (err_id, ))
74    fix = db.fetchall()
75
76    return (marker, columns_marker, elements, columns_elements, fix, columns_fix)
77
78
79@route('/error/<err_id:int>')
80def display(db, lang, err_id):
81    (marker, columns_marker, elements, columns_elements, fix, columns_fix) = _get(db, err_id)
82
83    return template('error/index', err_id=err_id,
84        marker=marker, columns_marker=columns_marker,
85        elements=elements, columns_elements=columns_elements,
86        fix=fix, columns_fix=columns_fix)
87
88
89@route('/api/0.2/error/<err_id:int>/fresh_elems')
90@route('/api/0.2/error/<err_id:int>/fresh_elems/<fix_num:int>')
91def fresh_elems(db, lang, err_id, fix_num=None):
92    (marker, columns_marker, elements, columns_elements, fix, columns_fix) = _get(db, err_id)
93
94    data_type = { "N": "node", "W": "way", "R": "relation", "I": "infos"}
95
96    def expand_tags(tags):
97      t = []
98      for (k, v) in tags.items():
99        t.append({"k": k, "v": v})
100      return t
101
102    elems = {}
103    for elem in elements:
104      if elem["data_type"]:
105        fresh_elem = utils.fetch_osm_elem(data_type[elem["data_type"]], elem["id"])
106
107        if fresh_elem and len(fresh_elem) > 0:
108            tmp_elem = {data_type[elem["data_type"]]: True,
109                    "type": data_type[elem["data_type"]],
110                    "id": elem["id"],
111                    "version": fresh_elem["version"],
112                    "tags": fresh_elem[u'tag'],
113                   }
114            elems[data_type[elem["data_type"]] + str(elem["id"])] = tmp_elem
115
116    if fix_num != None:
117        res = _get_fix(db, err_id, fix_num)
118        tid = data_type[res["elem_data_type"]] + str(res["elem_id"])
119        if elems.has_key(tid):
120            fix_elem_tags = copy.copy(elems[tid]["tags"])
121            for k in res["tags_delete"]:
122                if fix_elem_tags.has_key(k):
123                    del fix_elem_tags[k]
124            for (k, v) in res["tags_create"].items():
125                fix_elem_tags[k] = v
126            for (k, v) in res["tags_modify"].items():
127                fix_elem_tags[k] = v
128
129            ret = {
130                "error_id": err_id,
131                "elems": elems.values(),
132                "fix": {tid: fix_elem_tags}
133            }
134
135            for elem in ret['elems']:
136                elem["tags"] = expand_tags(elem["tags"])
137            return ret
138
139    ret = {
140        "error_id": err_id,
141        "elems": elems.values()
142    }
143
144    for elem in ret['elems']:
145        elem["tags"] = expand_tags(elem["tags"])
146
147    return ret
148
149
150@route('/api/0.2/error/<err_id:int>')
151def error(db, lang, err_id):
152    data_type = { "N": "node", "W": "way", "R": "relation", "I": "infos"}
153
154    # TRANSLATORS: link to tooltip help
155    url_help = _("http://wiki.openstreetmap.org/wiki/Osmose/errors")
156
157    translate = utils.translator(lang)
158
159    (marker, columns_marker, elements, columns_elements, fixies, columns_fix) = _get(db, err_id)
160
161    lat       = str(marker["lat"])
162    lon       = str(marker["lon"])
163    title     = translate.select(marker["title"])
164    subtitle  = translate.select(marker["subtitle"])
165    b_date    = marker["timestamp"] or ""
166    item      = marker["item"] or 0
167
168    def expand_tags(tags, links, short = False):
169      t = []
170      if short:
171        for k in tags:
172          t.append({"k": k})
173      else:
174        for (k, v) in sorted(tags.items()):
175          if links and links.has_key(k):
176            t.append({"k": k, "v": v, "vlink": links[k]})
177          else:
178            t.append({"k": k, "v": v})
179      return t
180
181    elems = []
182    for elem in elements:
183      if elem["data_type"]:
184        tags = elem["tags"]
185        try:
186            links = t2l.checkTags(tags)
187        except:
188            links = {}
189        tmp_elem = {data_type[elem["data_type"]]: True,
190                    "type": data_type[elem["data_type"]],
191                    "id": elem["id"],
192                    "tags": expand_tags(tags, links),
193                    "fixes": [],
194                   }
195        for fix in fixies:
196          if (fix["elem_data_type"] and
197              fix["elem_data_type"] == elem["data_type"] and
198              fix["elem_id"] == elem["id"]):
199            tmp_elem["fixes"].append({"num": fix["diff_index"],
200                                      "add": expand_tags(fix["tags_create"], {}),
201                                      "mod": expand_tags(fix["tags_modify"], {}),
202                                      "del": expand_tags(fix["tags_delete"], {}, True),
203                                     })
204        elems.append(tmp_elem)
205
206    new_elems = []
207    for fix in fixies:
208        if fix["elem_data_type"]:
209            found = False
210            for e in elems:
211                if (e["type"] == data_type[fix["elem_data_type"]] and
212                    e["id"] == fix[ "elem_id"]):
213
214                    found = True
215                    break
216            if not found:
217                new_elems.append({"num": fix["diff_index"],
218                                  "add": expand_tags(fix["tags_create"], {}),
219                                  "mod": expand_tags(fix["tags_modify"], {}),
220                                  "del": expand_tags(fix["tags_delete"], {}, True),
221                                 })
222
223    return {
224        "lat":lat, "lon":lon,
225        "minlat": float(lat) - 0.002, "maxlat": float(lat) + 0.002,
226        "minlon": float(lon) - 0.002, "maxlon": float(lon) + 0.002,
227        "error_id":err_id,
228        "title":title, "subtitle":subtitle,
229        "b_date":b_date.strftime("%Y-%m-%d"),
230        "item":item,
231        "elems":elems, "new_elems":new_elems,
232        "elems_id":marker["elems"].replace("_",","),
233        "url_help":url_help
234    }
235
236
237@route('/api/0.2/error/<err_id:int>/<status:re:(done|false)>')
238def status(err_id, status):
239    if osmose_common.remove_bug(err_id, status) == 0:
240        abort(200, "OK")
241    else:
242        abort(410, "FAIL")
243
244
245def _get_fix(db, err_id, fix_num):
246    columns = [ "diff_index", "elem_data_type", "elem_id", "tags_create", "tags_modify", "tags_delete" ]
247    sql = "SELECT " + ", ".join(columns) + """
248FROM marker_fix
249WHERE marker_id = %s AND diff_index = %s
250"""
251
252    db.execute(sql, (err_id, fix_num))
253    return db.fetchone()
254
255
256@route('/api/0.2/error/<err_id:int>/fix')
257@route('/api/0.2/error/<err_id:int>/fix/<fix_num:int>')
258def fix(db, err_id, fix_num=0):
259    res = _get_fix(db, err_id, fix_num)
260    if res:
261        response.content_type = 'text/xml; charset=utf-8'
262        if res["elem_id"] > 0:
263            out = StringIO.StringIO()
264            o = OsmSaxFixWriter(out, "UTF-8",
265                                res["elem_data_type"], res["elem_id"],
266                                res["tags_create"], res["tags_modify"], res["tags_delete"])
267            o.startDocument()
268
269            data_type = {"N": "node", "W": "way", "R": "relation"}
270            osm_read = utils.fetch_osm_data(data_type[res["elem_data_type"]], res["elem_id"])
271            osm_read.CopyTo(o)
272
273            return out.getvalue()
274
275        else:
276            # create new object
277            data = {}
278            data["id"] = -1
279            data["tag"] = {}
280            for (k, v) in res["tags_create"].iteritems():
281                data["tag"][k] = v
282            sql = "SELECT lat, lon FROM marker WHERE id = %s"
283            db.execute(sql, (err_id, ))
284            res2 = db.fetchone()
285            data["lat"] = res2["lat"]
286            data["lon"] = res2["lon"]
287
288            if res["elem_data_type"] == 'N':
289                return OsmSax.NodeToXml(data, full=True)
290            elif res["elem_data_type"] == 'W':
291                return OsmSax.WayToXml(data, full=True)
292            elif res["elem_data_type"] == 'R':
293                return OsmSax.RelationToXml(data, full=True)
294
295    else:
296        abort(412, "Precondition Failed")
297        #print "No issue found"
298
299
300class OsmSaxFixWriter(OsmSax.OsmSaxWriter):
301
302    def __init__(self,
303                 out, enc,
304                 elem_type, elem_id,
305                 tags_create, tags_modify, tags_delete):
306        OsmSax.OsmSaxWriter.__init__(self, out, enc)
307
308        self.elem_type = elem_type
309        self.elem_id = elem_id
310        self.tags_create = tags_create
311        self.tags_modify = tags_modify
312        self.tags_delete = tags_delete
313
314    def fix_tags(self, data):
315        for k in self.tags_delete:
316            del data["tag"][k]
317        for (k, v) in self.tags_create.items():
318            data["tag"][k] = v
319        for (k, v) in self.tags_modify.items():
320            data["tag"][k] = v
321        data["action"] = "modify"
322        return data
323
324    def NodeCreate(self, data):
325        if self.elem_type == "N" and self.elem_id == data["id"]:
326            data = self.fix_tags(data)
327        OsmSax.OsmSaxWriter.NodeCreate(self, data)
328
329    def WayCreate(self, data):
330        if self.elem_type == "W" and self.elem_id == data["id"]:
331            data = self.fix_tags(data)
332        OsmSax.OsmSaxWriter.WayCreate(self, data)
333
334    def RelationCreate(self, data):
335        if self.elem_type == "R" and self.elem_id == data["id"]:
336            data = self.fix_tags(data)
337        OsmSax.OsmSaxWriter.RelationCreate(self, data)
Note: See TracBrowser for help on using the repository browser.