From 1d081d1bc9fbc2c823ff282fb356c2d3450fd8ed Mon Sep 17 00:00:00 2001 From: Csenongmin Date: Tue, 21 Jul 2026 17:26:04 +0200 Subject: [PATCH] 07/21 add collection_patch --- .png | Bin 25963 -> 0 bytes openAPI/examples/collections.json | 2 +- pygeoapi/api/indoorgml.py | 37 +++++++- pygeoapi/flask_app.py | 4 +- pygeoapi/provider/postgresql_indoordb.py | 112 +++++++++-------------- requirements-indoor.txt | 54 ----------- 6 files changed, 80 insertions(+), 129 deletions(-) delete mode 100644 .png delete mode 100644 requirements-indoor.txt diff --git a/.png b/.png deleted file mode 100644 index 71f49edb6a4c586653a0435522a73189a272ec0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25963 zcmeFac{r8-`ak+04Wv+_$kc4iCn{l)M3F?M3=x$|tdPvCN+olBLZ8Y|l6k7kV}(^@ zXfR}2Wwp#hX3Kc)_p>zYefIvI-}(JN+z%Ul!9#@uj7tZ%Nw)gjJ*jR6hEu z#2+^(QO-~PsO@q{?(#r${mi(Dcyhs&fug?Ap3?@6-d&@L3Pw^9RZK8EY)2Sz4E>3H zORUVvPRz^Z~{We~|RoSfcNRUSO6$Ki1PGvBDoJNh|*U zFaLjL!KPiOd*U}mRFyk7nm2YoF5J{YEb;Q3coA(kwiCl{-hh+x_Fi9Ffs|vO*=+5? ztj+%>_KXQjC&%4g{ z+b9QYywW5x0ps!OUXjsR{g8Lr#>>Ypmds7aMK27Kg+e^r7YvxOP1j+FF(GDByw(+g ziG8*yW_f=VkEasLZ*Pm@qs$Gu%qY3g!i*{wW_%Wg>>_i_q{#flLav7wpC1ksRC3>Y zlMM@Hn>Sqr&v@l-=>;_E=rA*oqoJk~oxIv->dkO~#jNPW7n|s&(|>DsBqgUM5gK!r z8OB{6$tjt$d*s}30u7?+@+WPowa`oxsWb(Kagf)1?cdvUg0r);r|NDI)`loe+%Go4 zRNkQ5f8m(KI_rj%6PdJd(~8ED`SGc*%ar*Rra~6>TC&#j7XP@hx9gEp2aMB?=t<=t z&a3s3DqffyBBz{q@uZ+YLDao+?IuzC{GMmVFV0pkwHRd)no@b>J>A2_HSFRu=`vh2 z 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 diff --git a/openAPI/examples/collections.json b/openAPI/examples/collections.json index dd053582c..5d3c31ab3 100644 --- a/openAPI/examples/collections.json +++ b/openAPI/examples/collections.json @@ -66,7 +66,7 @@ "crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84" } }, - "itemType": "feature" + "itemType": "indoorfeature" }, { "id": "aist_waterfront_lab", diff --git a/pygeoapi/api/indoorgml.py b/pygeoapi/api/indoorgml.py index db15e7d4f..a127fda13 100644 --- a/pygeoapi/api/indoorgml.py +++ b/pygeoapi/api/indoorgml.py @@ -35,8 +35,7 @@ def manage_collection(api: API, request: APIRequest, action: str, dataset: str = headers = request.get_response_headers(SYSTEM_LOCALE) pidb_provider = PostgresIndoorDB() - # --- Action: CREATE --- - if action == 'create': + if action in ['create', 'update']: if not request.data: msg = 'No data found' LOGGER.error(msg) @@ -59,12 +58,24 @@ def manage_collection(api: API, request: APIRequest, action: str, dataset: str = return api.get_exception( HTTPStatus.BAD_REQUEST, headers, request.format, 'InvalidParameterValue', msg) - + + # --- Action: CREATE --- + if action == 'create': # 2. Call Provider to Create try: pidb_provider.connect() + c_id = data.get('id') + title = data.get('title') + item_type = data.get('itemType', 'indoorfeature') + if not c_id or not title: + return api.get_exception( + HTTPStatus.BAD_REQUEST, + headers, request.format, "Missing required parameter 'id' and 'title'.", msg) + elif item_type != 'indoorfeature': + return api.get_exception( + HTTPStatus.BAD_REQUEST, + headers, request.format, "Invalid 'itemType' value. Expected 'indoorfeature'.", msg) new_id = pidb_provider.post_collection(data) - if not new_id: return api.get_exception( HTTPStatus.CONFLICT, headers, request.format, @@ -97,6 +108,24 @@ def manage_collection(api: API, request: APIRequest, action: str, dataset: str = return api.get_exception(HTTPStatus.INTERNAL_SERVER_ERROR, headers, request.format, 'ServerError', str(e)) finally: pidb_provider.disconnect() + + elif action == 'update': + try: + pidb_provider.connect() + collection_id = str(dataset) + + success = pidb_provider.patch_collection(collection_id, data) + if not success: + return api.get_exception( + HTTPStatus.NOT_FOUND, headers, request.format, + 'NotFound', f'Collection {collection_id} not found') + + return headers, HTTPStatus.NO_CONTENT, 'Updated successfully.' + + except Exception as e: + return api.get_exception(HTTPStatus.INTERNAL_SERVER_ERROR, headers, request.format, 'ServerError', str(e)) + finally: + pidb_provider.disconnect() return headers, HTTPStatus.METHOD_NOT_ALLOWED, '' diff --git a/pygeoapi/flask_app.py b/pygeoapi/flask_app.py index 108773d55..7a9b75065 100644 --- a/pygeoapi/flask_app.py +++ b/pygeoapi/flask_app.py @@ -232,7 +232,7 @@ def get_tilematrix_sets(): @BLUEPRINT.route('/collections', methods=['GET', 'POST']) -@BLUEPRINT.route('/collections/', methods=['GET', 'DELETE']) +@BLUEPRINT.route('/collections/', methods=['GET', 'PATCH','DELETE']) def collections(collection_id: str | None = None): """ OGC API collections endpoint @@ -269,6 +269,8 @@ def collections(collection_id: str | None = None): elif request.method == 'DELETE': # Delete from DB return execute_from_flask(indoorgml.manage_collection, request, 'delete', collection_id) + elif request.method == 'PATCH': + return execute_from_flask(indoorgml.manage_collection, request, 'update', collection_id) # Fallback: Standard OGC API (YAML-based GeoJSON/CSV features) else: diff --git a/pygeoapi/provider/postgresql_indoordb.py b/pygeoapi/provider/postgresql_indoordb.py index 317dc511b..f8c41a69e 100644 --- a/pygeoapi/provider/postgresql_indoordb.py +++ b/pygeoapi/provider/postgresql_indoordb.py @@ -89,7 +89,6 @@ def get_collections_list(self): clean_list.append({ 'id': c_id, - # Default to the ID if title is missing 'title': props.get('title', c_id), 'itemType': props.get('itemType', 'indoorfeature') }) @@ -163,7 +162,6 @@ def post_collection(self, collection): } with self.connection.cursor() as cur: try: - # 2. Insert (Let Postgres handle the 'id' column automatically) insert_query = """ INSERT INTO collection (id_str, collection_property) VALUES (%s, %s) @@ -228,8 +226,47 @@ def delete_collection(self, collection_id:str): self.connection.rollback() LOGGER.error(f"Error creating collection: {e}") raise e + + + def patch_collection(self, collection_id:str, data): + with self.connection.cursor() as cur: + try: + cur.execute("SELECT id FROM collection WHERE id_str = %s", (collection_id,)) + row = cur.fetchone() + + if not row: + return False # Collection not found + + coll_pk = row[0] + + sql = "SELECT collection_property FROM collection WHERE id = %s" + cur.execute(sql, (coll_pk,)) + + collection_json = cur.fetchone() + + fields = [] + values = [] + + if 'title' in data: + collection_json['title'] = data['title'] + + if 'description' in data: + collection_json['description'] = data['description'] + + update_sql = "UPDATE collection SET collection_property = %s WHERE id = %s" + cur.execute(update_sql, (json.dumps(collection_json),coll_pk,)) + + self.connection.commit() + return True + + except Exception as e: + self.connection.rollback() + LOGGER.error(f"Error updating collection: {e}") + raise e + # endregion + # region IndoorFeatures def is_indoor_collection(self, collection_id:str): """ @@ -260,7 +297,6 @@ def get_collection_items( """ Retrieve the indoor feature collection /collections/{collectionId}/items Optimized to fetch data and total count in a single query. - /collections/{collectionId}/items """ try: # 1. Prepare Filter Strings @@ -363,7 +399,6 @@ def get_feature(self, collection_id: str, feature_id:str, level:str=None, bbox:l properties = props or {} thematic_layers = [] interlayer_connections = [] - # Initialize Skeleton result_feature = { "type": "Feature", "id": feature_id_str, @@ -512,7 +547,6 @@ def delete_indoorfeature(self, collection_id:str, feature_id:str): res = cur.fetchone() if not res: - # Item not found, usually returns 404 in API, but here we can just return msg = f"Feature {feature_id} not found." LOGGER.warning(msg) raise ValueError(msg) @@ -543,7 +577,6 @@ def delete_indoorfeature(self, collection_id:str, feature_id:str): # 3. DELETE PARENT (The IndoorFeature itself) cur.execute("DELETE FROM indoorfeature WHERE id = %s", (feature_pk,)) - # Commit is handled by the context manager self.connection.commit() return True except Exception as e: @@ -660,7 +693,7 @@ def get_layers(self, collection_id:str, feature_id:str, theme: str = None, level def _get_layer(self, layer_pk:int, level:str=None, bbox:list=None): """ - Retrieves a single Thematic Layer. + Retrieves a single Thematic Layer with Integer ID. If not filtered, just the meta data is given. - PrimalSpace: Filtered by 'level' if provided. - DualSpace: Returns the ENTIRE network (unfiltered) for connectivity. @@ -703,7 +736,7 @@ def _get_layer(self, layer_pk:int, level:str=None, bbox:list=None): def get_layer(self, collection_id:str, feature_id:str, layer_id:str, level:str=None, bbox:list=None): """ - Retrieves a single Thematic Layer. + Retrieves a single Thematic Layer with String ID. If not filtered, just the meta data is given. - PrimalSpace: Filtered by 'level' if provided. - DualSpace: Returns the ENTIRE network (unfiltered) for connectivity. @@ -817,7 +850,7 @@ def get_layer(self, collection_id:str, feature_id:str, layer_id:str, level:str=N def _get_primal_space(self, layer_pk:int, primalspace_id:str, p_create:str = None, p_termination:str=None, level:str=None, bbox:list=None): """ Helper to build PrimalSpaceLayer. - Supports optional filtering by 'level'. + Supports optional filtering by 'level' and 'bbox'. """ primal_space = { "id": primalspace_id, @@ -1053,7 +1086,7 @@ def _post_thematic_layer(self, collection_pk:int, feature_pk:int, layer_data): layer_new = cur.fetchone() - # Insert Primal Members (Cells/Boundaries) - returns duality dict + # Insert Primal Members (Cells/Boundaries) - returns duality dictionary d_c, d_b = self._post_primal_members(collection_pk, feature_pk, layer_new[0], primal) # Insert Dual Members (Nodes/Edges) @@ -1168,65 +1201,6 @@ def _post_primal_members(self, collection_pk:int, feature_pk:int, layer_pk:int, # If there is no 2D geometry but 3D, project 3D to 2D geometry LOGGER.debug("Project geometry 3D to 2D ") sql_project_shell = """ - WITH faces AS ( - SELECT - c.id, - s.shell_idx, - f.face - FROM cell_space_n_boundary c - CROSS JOIN LATERAL jsonb_array_elements(c."3D_geometry"->'coordinates') - WITH ORDINALITY AS s(shell, shell_idx) - CROSS JOIN LATERAL jsonb_array_elements(s.shell) AS f(face) - WHERE c."3D_geometry" IS NOT NULL - AND c.type = 'space' - AND c."2D_geometry" IS NULL - AND c.thematiclayer_id = %s - AND ( - s.shell_idx = 1 - OR jsonb_array_length(c."3D_geometry"->'coordinates') > 1 - ) - ), - proj AS ( - SELECT - id, - shell_idx, - ST_SetSRID( - ST_Force2D( - ST_GeomFromGeoJSON( - jsonb_build_object( - 'type', 'Polygon', - 'coordinates', - CASE - -- if face is already [ring,...], keep it; else wrap to [ring] - WHEN jsonb_typeof(face->0->0) = 'array' THEN face - ELSE jsonb_build_array(face) - END - )::text - ) - ), - 0 - ) AS g2d - FROM faces - ), - u AS ( - SELECT - id, - ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx = 1) ) AS ext2d, - ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx > 1) ) AS int2d - FROM proj - GROUP BY id - ) - UPDATE cell_space_n_boundary c - SET "2D_geometry" = - CASE - WHEN u.int2d IS NULL THEN u.ext2d - ELSE ST_Difference(u.ext2d, u.int2d) - END - FROM u - WHERE c.id = u.id - AND c.thematiclayer_id = %s; - """ - sql_project_shell = """ WITH targets AS ( SELECT id, "3D_geometry" FROM cell_space_n_boundary diff --git a/requirements-indoor.txt b/requirements-indoor.txt deleted file mode 100644 index d44d0b4fa..000000000 --- a/requirements-indoor.txt +++ /dev/null @@ -1,54 +0,0 @@ -affine==2.4.0 -annotated-types==0.7.0 -attrs==25.4.0 -babel==2.17.0 -blinker==1.9.0 -certifi==2026.1.4 -charset-normalizer==3.4.4 -click==8.3.1 -cligj==0.7.2 -contourpy==1.3.3 -cycler==0.12.1 -dateparser==1.2.2 -filelock==3.20.3 -Flask==3.1.2 -flask-cors==6.0.2 -fonttools==4.61.1 -GeoAlchemy2==0.18.1 -greenlet==3.3.0 -idna==3.11 -itsdangerous==2.2.0 -Jinja2==3.1.6 -jsonschema==4.26.0 -jsonschema-specifications==2025.9.1 -kiwisolver==1.4.9 -lark==1.3.1 -MarkupSafe==3.0.3 -matplotlib==3.10.8 -numpy==2.4.1 -packaging==25.0 -pillow==12.1.0 -psycopg2-binary==2.9.11 -pydantic==2.12.5 -pydantic_core==2.41.5 -pygeofilter==0.3.3 -pygeoif==1.6.0 -pyparsing==3.3.1 -pyproj==3.7.2 -python-dateutil==2.9.0.post0 -pytz==2025.2 -PyYAML==6.0.3 -rasterio==1.5.0 -referencing==0.37.0 -regex==2026.1.15 -requests==2.32.5 -rpds-py==0.30.0 -shapely==2.1.2 -six==1.17.0 -SQLAlchemy==2.0.45 -tinydb==4.8.2 -typing-inspection==0.4.2 -typing_extensions==4.15.0 -tzlocal==5.3.1 -urllib3==2.6.3 -Werkzeug==3.1.5