forked from s_ranjbar/city_retrofit
Full implementation of basic persistence tasks for the one_shot admin tool.
This commit is contained in:
parent
a34206e6ff
commit
16adfaa1a8
|
@ -6,6 +6,8 @@ Project CoderPeter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
from hub.persistence import City
|
from hub.persistence import City
|
||||||
from hub.persistence import Application
|
from hub.persistence import Application
|
||||||
|
from hub.persistence import User
|
||||||
|
from hub.persistence import CityObject
|
||||||
|
|
||||||
|
|
||||||
class DBFactory:
|
class DBFactory:
|
||||||
|
@ -16,6 +18,8 @@ class DBFactory:
|
||||||
def __init__(self, db_name, app_env, dotenv_path):
|
def __init__(self, db_name, app_env, dotenv_path):
|
||||||
self._city = City(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
self._city = City(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
self._application = Application(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
self._application = Application(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
|
self._user = User(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
|
self._city_object = CityObject(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
|
|
||||||
def get_city(self, city_id):
|
def get_city(self, city_id):
|
||||||
"""
|
"""
|
||||||
|
@ -41,3 +45,9 @@ class DBFactory:
|
||||||
def application_info(self, application_uuid):
|
def application_info(self, application_uuid):
|
||||||
return self._application.get_by_uuid(application_uuid)
|
return self._application.get_by_uuid(application_uuid)
|
||||||
|
|
||||||
|
def user_info(self, name, password, application_id):
|
||||||
|
return self._user.get_by_name_application_and_password(name, password, application_id)
|
||||||
|
|
||||||
|
def building_info(self, name, city_id):
|
||||||
|
return self._city_object.get_by_name_and_city(name, city_id)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ Project CoderPeter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
from hub.city_model_structure.city import City
|
from hub.city_model_structure.city import City
|
||||||
from hub.persistence import City as CityRepository
|
from hub.persistence import City as CityRepository
|
||||||
|
from hub.persistence import SimulationResults
|
||||||
|
|
||||||
|
|
||||||
class DBFactory:
|
class DBFactory:
|
||||||
|
@ -15,10 +16,14 @@ class DBFactory:
|
||||||
|
|
||||||
def __init__(self, db_name, dotenv_path, app_env):
|
def __init__(self, db_name, dotenv_path, app_env):
|
||||||
self._city_repository = CityRepository(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
self._city_repository = CityRepository(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||||
|
self._simulation_results = SimulationResults(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||||
|
|
||||||
def persist_city(self, application_id: int, user_id: int, city: City):
|
def persist_city(self, city: City, application_id: int, user_id: int):
|
||||||
"""
|
"""
|
||||||
Persist city into postgres database
|
Persist city into postgres database
|
||||||
|
:param city: City to be stored
|
||||||
|
:param application_id: Application id owning this city
|
||||||
|
:param user_id: User who create the city
|
||||||
"""
|
"""
|
||||||
return self._city_repository.insert(city, application_id, user_id)
|
return self._city_repository.insert(city, application_id, user_id)
|
||||||
|
|
||||||
|
@ -36,3 +41,13 @@ class DBFactory:
|
||||||
:param city_id: the id of the city to get
|
:param city_id: the id of the city to get
|
||||||
"""
|
"""
|
||||||
self._city_repository.delete(city_id)
|
self._city_repository.delete(city_id)
|
||||||
|
|
||||||
|
def add_simulation_results(self, name, values, city_id=None, city_object_id=None):
|
||||||
|
"""
|
||||||
|
Add simulation results to the city or to the city_object
|
||||||
|
:param name: simulation and simulation engine name
|
||||||
|
:param values: simulation values in json format
|
||||||
|
:param city_id: city id or None
|
||||||
|
:param city_object_id: city object id or None
|
||||||
|
"""
|
||||||
|
self._simulation_results.insert(name, values,city_id, city_object_id)
|
||||||
|
|
|
@ -19,12 +19,18 @@ class CityGml:
|
||||||
"""
|
"""
|
||||||
CityGml class
|
CityGml class
|
||||||
"""
|
"""
|
||||||
def __init__(self, path, extrusion_height_field=None, year_of_construction_field=None, function_field=None):
|
def __init__(self,
|
||||||
|
path,
|
||||||
|
extrusion_height_field=None,
|
||||||
|
year_of_construction_field='yearOfConstruction',
|
||||||
|
function_field='function',
|
||||||
|
function_to_hub=None):
|
||||||
self._city = None
|
self._city = None
|
||||||
self._lod = None
|
self._lod = None
|
||||||
self._lod1_tags = ['lod1Solid', 'lod1MultiSurface']
|
self._lod1_tags = ['lod1Solid', 'lod1MultiSurface']
|
||||||
self._lod2_tags = ['lod2Solid', 'lod2MultiSurface', 'lod2MultiCurve']
|
self._lod2_tags = ['lod2Solid', 'lod2MultiSurface', 'lod2MultiCurve']
|
||||||
self._extrusion_height_field = extrusion_height_field
|
self._extrusion_height_field = extrusion_height_field
|
||||||
|
self._function_to_hub = function_to_hub
|
||||||
self._year_of_construction_field = year_of_construction_field
|
self._year_of_construction_field = year_of_construction_field
|
||||||
if function_field is None:
|
if function_field is None:
|
||||||
function_field = 'function'
|
function_field = 'function'
|
||||||
|
@ -110,12 +116,15 @@ class CityGml:
|
||||||
name = city_object['@id']
|
name = city_object['@id']
|
||||||
function = None
|
function = None
|
||||||
year_of_construction = None
|
year_of_construction = None
|
||||||
if 'yearOfConstruction' in city_object:
|
if self._year_of_construction_field in city_object:
|
||||||
year_of_construction = city_object['yearOfConstruction']
|
year_of_construction = city_object[self._year_of_construction_field]
|
||||||
if 'function' in city_object:
|
if self._function_field in city_object:
|
||||||
function = city_object[self._function_field]
|
function = city_object[self._function_field]
|
||||||
if type(function) != str:
|
if type(function) != str:
|
||||||
function = function['#text']
|
function = function['#text']
|
||||||
|
if self._function_to_hub is not None:
|
||||||
|
# use the transformation dictionary to retrieve the proper function
|
||||||
|
function = self._function_to_hub[function]
|
||||||
|
|
||||||
if any(key in city_object for key in self._lod1_tags):
|
if any(key in city_object for key in self._lod1_tags):
|
||||||
if self._lod is None or self._lod > 1:
|
if self._lod is None or self._lod > 1:
|
||||||
|
|
|
@ -26,7 +26,12 @@ class Geojson:
|
||||||
X = 0
|
X = 0
|
||||||
Y = 1
|
Y = 1
|
||||||
|
|
||||||
def __init__(self, path, extrusion_height_field=None, year_of_construction_field=None, function_field=None):
|
def __init__(self,
|
||||||
|
path,
|
||||||
|
extrusion_height_field=None,
|
||||||
|
year_of_construction_field=None,
|
||||||
|
function_field=None,
|
||||||
|
function_to_hub=None):
|
||||||
# todo: destination epsg should change according actual the location
|
# todo: destination epsg should change according actual the location
|
||||||
self._transformer = Transformer.from_crs('epsg:4326', 'epsg:26911')
|
self._transformer = Transformer.from_crs('epsg:4326', 'epsg:26911')
|
||||||
self._min_x = cte.MAX_FLOAT
|
self._min_x = cte.MAX_FLOAT
|
||||||
|
@ -38,6 +43,7 @@ class Geojson:
|
||||||
self._extrusion_height_field = extrusion_height_field
|
self._extrusion_height_field = extrusion_height_field
|
||||||
self._year_of_construction_field = year_of_construction_field
|
self._year_of_construction_field = year_of_construction_field
|
||||||
self._function_field = function_field
|
self._function_field = function_field
|
||||||
|
self._function_to_hub = function_to_hub
|
||||||
with open(path) as json_file:
|
with open(path) as json_file:
|
||||||
self._geojson = json.loads(json_file.read())
|
self._geojson = json.loads(json_file.read())
|
||||||
|
|
||||||
|
@ -118,6 +124,9 @@ class Geojson:
|
||||||
function = None
|
function = None
|
||||||
if self._function_field is not None:
|
if self._function_field is not None:
|
||||||
function = feature['properties'][self._function_field]
|
function = feature['properties'][self._function_field]
|
||||||
|
if self._function_to_hub is not None:
|
||||||
|
# use the transformation dictionary to retrieve the proper function
|
||||||
|
function = self._function_to_hub[function]
|
||||||
geometry = feature['geometry']
|
geometry = feature['geometry']
|
||||||
if 'id' in feature:
|
if 'id' in feature:
|
||||||
building_name = feature['id']
|
building_name = feature['id']
|
||||||
|
|
|
@ -26,7 +26,8 @@ class GeometryFactory:
|
||||||
data_frame=None,
|
data_frame=None,
|
||||||
height_field=None,
|
height_field=None,
|
||||||
year_of_construction_field=None,
|
year_of_construction_field=None,
|
||||||
function_field=None):
|
function_field=None,
|
||||||
|
function_to_hub=None):
|
||||||
self._file_type = '_' + file_type.lower()
|
self._file_type = '_' + file_type.lower()
|
||||||
class_funcs = validate_import_export_type(GeometryFactory)
|
class_funcs = validate_import_export_type(GeometryFactory)
|
||||||
if self._file_type not in class_funcs:
|
if self._file_type not in class_funcs:
|
||||||
|
@ -38,6 +39,7 @@ class GeometryFactory:
|
||||||
self._height_field = height_field
|
self._height_field = height_field
|
||||||
self._year_of_construction_field = year_of_construction_field
|
self._year_of_construction_field = year_of_construction_field
|
||||||
self._function_field = function_field
|
self._function_field = function_field
|
||||||
|
self._function_to_hub = function_to_hub
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _citygml(self) -> City:
|
def _citygml(self) -> City:
|
||||||
|
@ -45,7 +47,11 @@ class GeometryFactory:
|
||||||
Enrich the city by using CityGML information as data source
|
Enrich the city by using CityGML information as data source
|
||||||
:return: City
|
:return: City
|
||||||
"""
|
"""
|
||||||
return CityGml(self._path, self._height_field, self._year_of_construction_field, self._function_field).city
|
return CityGml(self._path,
|
||||||
|
self._height_field,
|
||||||
|
self._year_of_construction_field,
|
||||||
|
self._function_field,
|
||||||
|
self._function_to_hub).city
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _obj(self) -> City:
|
def _obj(self) -> City:
|
||||||
|
@ -71,7 +77,11 @@ class GeometryFactory:
|
||||||
Enrich the city by using Geojson information as data source
|
Enrich the city by using Geojson information as data source
|
||||||
:return: City
|
:return: City
|
||||||
"""
|
"""
|
||||||
return Geojson(self._path, self._height_field, self._year_of_construction_field, self._function_field).city
|
return Geojson(self._path,
|
||||||
|
self._height_field,
|
||||||
|
self._year_of_construction_field,
|
||||||
|
self._function_field,
|
||||||
|
self._function_to_hub).city
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _osm_subway(self) -> City:
|
def _osm_subway(self) -> City:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from .repository import Repository
|
from .repository import Repository
|
||||||
from .repositories.city import City
|
from .repositories.city import City
|
||||||
from .repositories.application import Application
|
from .repositories.application import Application
|
||||||
|
from .repositories.simulation_results import SimulationResults
|
||||||
|
from .repositories.city_object import CityObject
|
||||||
from .db_setup import DBSetup
|
from .db_setup import DBSetup
|
||||||
from .repositories.user import User
|
from .repositories.user import User
|
||||||
from .models.user import UserRoles
|
from .models.user import UserRoles
|
||||||
|
|
|
@ -16,6 +16,7 @@ from hub.city_model_structure.city import City as CityHub
|
||||||
from hub.hub_logger import logger
|
from hub.hub_logger import logger
|
||||||
from hub.persistence import Repository
|
from hub.persistence import Repository
|
||||||
from hub.persistence.models import City as Model
|
from hub.persistence.models import City as Model
|
||||||
|
from hub.persistence.models import CityObject
|
||||||
from hub.version import __version__
|
from hub.version import __version__
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,17 +46,35 @@ class City(Repository):
|
||||||
db_city = Model(
|
db_city = Model(
|
||||||
pickle.dumps(city),
|
pickle.dumps(city),
|
||||||
city.name,
|
city.name,
|
||||||
city.level_of_detail,
|
city.level_of_detail.geometry,
|
||||||
city.climate_file,
|
'None' if city.climate_file is None else city.climate_file,
|
||||||
application_id,
|
application_id,
|
||||||
user_id,
|
user_id,
|
||||||
__version__)
|
__version__)
|
||||||
|
|
||||||
self.session.add(db_city)
|
self.session.add(db_city)
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
|
for building in city.buildings:
|
||||||
|
object_usage = ''
|
||||||
|
for internal_zone in building.internal_zones:
|
||||||
|
for usage in internal_zone.usages:
|
||||||
|
object_usage = f'{object_usage}{usage.name}_{usage.percentage} '
|
||||||
|
object_usage = object_usage.rstrip()
|
||||||
|
db_city_object = CityObject(db_city.id,
|
||||||
|
building.name,
|
||||||
|
building.alias,
|
||||||
|
building.type,
|
||||||
|
building.year_of_construction,
|
||||||
|
building.function,
|
||||||
|
object_usage,
|
||||||
|
building.volume,
|
||||||
|
building.floor_area)
|
||||||
|
self.session.add(db_city_object)
|
||||||
|
self.session.flush()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
return db_city
|
return db_city
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
|
print(f'An error occurred while creating city: {err}')
|
||||||
logger.error(f'An error occurred while creating city: {err}')
|
logger.error(f'An error occurred while creating city: {err}')
|
||||||
|
|
||||||
def update(self, city_id: int, city: CityHub):
|
def update(self, city_id: int, city: CityHub):
|
||||||
|
|
|
@ -77,7 +77,7 @@ class CityObject(Repository):
|
||||||
for usage in internal_zone.usages:
|
for usage in internal_zone.usages:
|
||||||
object_usage = f'{object_usage}{usage.name}_{usage.percentage} '
|
object_usage = f'{object_usage}{usage.name}_{usage.percentage} '
|
||||||
object_usage = object_usage.rstrip()
|
object_usage = object_usage.rstrip()
|
||||||
self.session.query(Model).filter(Model.name == building.name and Model.city_id == city_id).update(
|
self.session.query(Model).filter(Model.name == building.name, Model.city_id == city_id).update(
|
||||||
{'name': building.name,
|
{'name': building.name,
|
||||||
'alias': building.alias,
|
'alias': building.alias,
|
||||||
'object_type': building.type,
|
'object_type': building.type,
|
||||||
|
@ -100,7 +100,7 @@ class CityObject(Repository):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.session.query(Model).filter(Model.city_id == city_id and Model.name == name).delete()
|
self.session.query(Model).filter(Model.city_id == city_id, Model.name == name).delete()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while deleting application: {err}')
|
logger.error(f'Error while deleting application: {err}')
|
||||||
|
@ -113,8 +113,13 @@ class CityObject(Repository):
|
||||||
:return: [CityObject] with the provided name belonging to the city with id city_id
|
:return: [CityObject] with the provided name belonging to the city with id city_id
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.session.execute(select(Model).where(
|
_city_object = self.session.execute(select(Model).where(
|
||||||
Model.name == name and Model.city_id == city_id
|
Model.name == name, Model.city_id == city_id
|
||||||
)).first()
|
)).first()
|
||||||
|
print(city_id, name, _city_object)
|
||||||
|
if _city_object is None:
|
||||||
|
return None
|
||||||
|
return _city_object[0]
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
|
print(err)
|
||||||
logger.error(f'Error while fetching application by application_uuid: {err}')
|
logger.error(f'Error while fetching application by application_uuid: {err}')
|
||||||
|
|
|
@ -74,14 +74,14 @@ class SimulationResults(Repository):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if city_id is not None:
|
if city_id is not None:
|
||||||
self.session.query(Model).filter(Model.name == name and Model.city_id == city_id).update(
|
self.session.query(Model).filter(Model.name == name, Model.city_id == city_id).update(
|
||||||
{
|
{
|
||||||
'values': values,
|
'values': values,
|
||||||
'updated': datetime.datetime.utcnow()
|
'updated': datetime.datetime.utcnow()
|
||||||
})
|
})
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
elif city_object_id is not None:
|
elif city_object_id is not None:
|
||||||
self.session.query(Model).filter(Model.name == name and Model.city_object_id == city_object_id).update(
|
self.session.query(Model).filter(Model.name == name, Model.city_object_id == city_object_id).update(
|
||||||
{
|
{
|
||||||
'values': values,
|
'values': values,
|
||||||
'updated': datetime.datetime.utcnow()
|
'updated': datetime.datetime.utcnow()
|
||||||
|
@ -104,10 +104,10 @@ class SimulationResults(Repository):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if city_id is not None:
|
if city_id is not None:
|
||||||
self.session.query(Model).filter(Model.name == name and Model.city_id == city_id).delete()
|
self.session.query(Model).filter(Model.name == name, Model.city_id == city_id).delete()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
elif city_object_id is not None:
|
elif city_object_id is not None:
|
||||||
self.session.query(Model).filter(Model.name == name and Model.city_object_id == city_object_id).delete()
|
self.session.query(Model).filter(Model.name == name, Model.city_object_id == city_object_id).delete()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
else:
|
else:
|
||||||
return {'message': 'Missing either city_id or city_object_id'}
|
return {'message': 'Missing either city_id or city_object_id'}
|
||||||
|
|
|
@ -94,12 +94,12 @@ class User(Repository):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.session.execute(
|
return self.session.execute(
|
||||||
select(Model).where(Model.name == name and Model.application_id == application_id)
|
select(Model).where(Model.name == name, Model.application_id == application_id)
|
||||||
).first()
|
).first()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching user by name and application: {err}')
|
logger.error(f'Error while fetching user by name and application: {err}')
|
||||||
|
|
||||||
def get_user_by_name_application_and_password(self, name: str, password: str, application_id: int) -> [Model]:
|
def get_by_name_application_and_password(self, name: str, password: str, application_id: int) -> [Model]:
|
||||||
"""
|
"""
|
||||||
Fetch user based on the email and password
|
Fetch user based on the email and password
|
||||||
:param name: User name
|
:param name: User name
|
||||||
|
@ -110,11 +110,11 @@ class User(Repository):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
user = self.session.execute(
|
user = self.session.execute(
|
||||||
select(Model).where(Model.name == name and Model.application_id == application_id)
|
select(Model).where(Model.name == name, Model.application_id == application_id)
|
||||||
).first()
|
).first()
|
||||||
if user:
|
if user:
|
||||||
if Auth.check_password(password, user[0].password):
|
if Auth.check_password(password, user[0].password):
|
||||||
return user
|
return user[0]
|
||||||
return {'message': 'invalid login information'}
|
return {'message': 'invalid login information'}
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching user by email: {err}')
|
logger.error(f'Error while fetching user by email: {err}')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user