from typing import Any from ..core.database import ( ChangeSet, DatabaseCommand, execute_command, g_add_prefix, g_delete_prefix, g_update_prefix, read_all, sql_literal, try_read, ) def get_label_schema(name: str) -> dict[str, dict[str, Any]]: return { 'x' : {'type': 'float' , 'optional': False , 'readonly': False}, 'y' : {'type': 'float' , 'optional': False , 'readonly': False}, 'label' : {'type': 'str' , 'optional': False , 'readonly': False}, 'node' : {'type': 'str' , 'optional': True , 'readonly': False} } def get_label(name: str, x: float, y: float) -> dict[str, Any]: d = {} d['x'] = x d['y'] = y l = try_read(name, "select label, node_id as node from gis.labels where geom = st_setsrid(st_makepoint(%s, %s), 900914)", (x, y)) if l == None: d['label'] = None d['node'] = None else: d['label'] = str(l['label']) d['node'] = str(l['node']) if l['node'] != None else None return d class Label(object): def __init__(self, input: dict[str, Any]) -> None: self.type = 'label' self.x = float(input['x']) self.y = float(input['y']) self.label = str(input['label']) self.node = str(input['node']) if 'node' in input and input['node'] != None else None self.f_type = sql_literal(self.type) self.f_x = sql_literal(self.x) self.f_y = sql_literal(self.y) self.f_label = sql_literal(self.label) self.f_node = sql_literal(self.node) def as_dict(self) -> dict[str, Any]: return { 'type': self.type, 'x': self.x, 'y': self.y, 'label': self.label, 'node': self.node } def _set_label(name: str, cs: ChangeSet) -> DatabaseCommand: raw_new = get_label(name, cs.operations[0]['x'], cs.operations[0]['y']) new_dict = cs.operations[0] schema = get_label_schema(name) for key, value in schema.items(): if key in new_dict and not value['readonly']: raw_new[key] = new_dict[key] new = Label(raw_new) statement = f"update gis.labels set label = {new.f_label}, node_id = {new.f_node} where geom = st_setsrid(st_makepoint({new.f_x}, {new.f_y}), 900914);" change = g_update_prefix | new.as_dict() return DatabaseCommand(statement, [change]) def set_label(name: str, cs: ChangeSet) -> ChangeSet: return execute_command(name, _set_label(name, cs)) def _add_label(name: str, cs: ChangeSet) -> DatabaseCommand: new = Label(cs.operations[0]) statement = f"insert into gis.labels (id, node_id, label, geom) values ((select coalesce(max(id) + 1, 1) from gis.labels), {new.f_node}, {new.f_label}, st_setsrid(st_makepoint({new.f_x}, {new.f_y}), 900914));" change = g_add_prefix | new.as_dict() return DatabaseCommand(statement, [change]) def add_label(name: str, cs: ChangeSet) -> ChangeSet: return execute_command(name, _add_label(name, cs)) def _delete_label(name: str, cs: ChangeSet) -> DatabaseCommand: x = float(cs.operations[0]['x']) y = float(cs.operations[0]['y']) f_x = sql_literal(x) f_y = sql_literal(y) statement = f"delete from gis.labels where geom = st_setsrid(st_makepoint({f_x}, {f_y}), 900914);" change = g_delete_prefix | {'type': 'label', 'x': x, 'y': y} return DatabaseCommand(statement, [change]) def delete_label(name: str, cs: ChangeSet) -> ChangeSet: return execute_command(name, _delete_label(name, cs)) def inp_in_label(line: str) -> str: tokens = line.split() num = len(tokens) has_desc = tokens[-1].startswith(';') num_without_desc = (num - 1) if has_desc else num x = float(tokens[0]) y = float(tokens[1]) label = str(tokens[2]) node = str(tokens[3]) if num >= 4 else None return str(f"insert into gis.labels (id, node_id, label, geom) values ((select coalesce(max(id) + 1, 1) from gis.labels), {sql_literal(node)}, {sql_literal(label)}, st_setsrid(st_makepoint({sql_literal(x)}, {sql_literal(y)}), 900914));") def inp_out_label(name: str) -> list[str]: lines = [] objs = read_all(name, 'select st_x(geom) as x, st_y(geom) as y, label, node_id as node from gis.labels order by id') for obj in objs: x = obj['x'] y = obj['y'] label = obj['label'] node = obj['node'] if obj['node'] != None else '' lines.append(f'{x} {y} {label} {node}') return lines def unset_label_by_node(name: str, node: str) -> ChangeSet: cs = ChangeSet() rows = read_all(name, "select st_x(geom) as x, st_y(geom) as y from gis.labels where node_id = %s", (node,)) for row in rows: cs.append(g_update_prefix | {'type': 'label', 'x': row['x'], 'y': row['y'], 'node': None}) return cs