From 7521482c3e58c04cf959ac4d2d852441d9f2cd5e Mon Sep 17 00:00:00 2001
From: jokiefer <jonas.kiefer@live.com>
Date: Thu, 25 May 2023 08:40:55 +0200
Subject: [PATCH] fixes #8

---
 CHANGELOG.rst                     |  9 ++++--
 ows_lib/models/ogc_request.py     | 50 ++++++++++++++++---------------
 tests/models/tests_ogc_request.py |  9 ++++--
 3 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e854313..ff74f61 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -7,14 +7,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 
-[unreleased] - 2023-xx-xx
+[v0.3.0] - 2023-05-25
 -------------------------
 
 Changed
 ~~~~~~~
 
-* improves development documentation
+* improves development documentation section
+* `ogc_query_params` now can handle multi value queryparams and only returns ogc queryparams that are present with a value.
 
+Removed 
+~~~~~~~
+
+* `params_lower` property from `OGCRequest` model.
 
 
 [v0.2.0] - 2023-05-17
diff --git a/ows_lib/models/ogc_request.py b/ows_lib/models/ogc_request.py
index 27b68d7..1854d49 100644
--- a/ows_lib/models/ogc_request.py
+++ b/ows_lib/models/ogc_request.py
@@ -19,16 +19,16 @@ class OGCRequest(Request):
 
     def __init__(self, *args, **kwargs) -> None:
         super().__init__(*args, **kwargs)
-        self._params_lower: dict = {}
-        self._ogc_query_params: dict = {}
+        self._ogc_query_params: Dict = {}
         self._bbox: GEOSGeometry = None
         self._requested_entities: List[str] = []
         self._xml_request: XmlObject = None
 
         if self.method == "GET":
-            self.operation: str = self.params_lower.get("request", "")
-            self.service_version: str = self.params_lower.get("version", "")
-            self.service_type: str = self.params_lower.get("service", "")
+            self.operation: str = self.ogc_query_params.get("REQUEST", "")
+            self.service_version: str = self.ogc_query_params.get(
+                "VERSION", "")
+            self.service_type: str = self.ogc_query_params.get("SERVICE", "")
         elif self.method == "POST":
             post_request: PostRequest = load_xmlobject_from_string(
                 string=self.data, xmlclass=PostRequest)
@@ -49,12 +49,12 @@ def requested_entities(self) -> List[str]:
         if not self._requested_entities:
             if self.is_wms:
                 self._requested_entities.extend(
-                    get_requested_layers(params=self.params_lower))
+                    get_requested_layers(params=self.ogc_query_params))
             else:
                 if self.is_get_feature_request:
                     if self.is_get:
                         self._requested_entities.extend(
-                            get_requested_feature_types(params=self.params_lower))
+                            get_requested_feature_types(params=self.ogc_query_params))
                     elif self.is_post:
                         self._requested_entities.extend(
                             self.xml_request.requested_feature_types)
@@ -103,7 +103,7 @@ def is_get_capabilities_request(self) -> bool:
         :return: true if this is a get capabilities request
         :rtype: bool
         """
-        return self.operation.lower() == OGCOperationEnum.GET_CAPABILITIES.value.lower()
+        return self.operation == OGCOperationEnum.GET_CAPABILITIES.value
 
     @property
     def is_get_map_request(self) -> bool:
@@ -112,7 +112,7 @@ def is_get_map_request(self) -> bool:
         :return: true if this is a wms get map request
         :rtype: bool
         """
-        return self.operation.lower() == OGCOperationEnum.GET_MAP.value.lower()
+        return self.operation == OGCOperationEnum.GET_MAP.value
 
     @property
     def is_get_feature_info_request(self) -> bool:
@@ -121,7 +121,7 @@ def is_get_feature_info_request(self) -> bool:
         :return: true if this is a wfs tranasction request
         :rtype: bool
         """
-        return self.operation.lower() == OGCOperationEnum.GET_FEATURE_INFO.value.lower()
+        return self.operation == OGCOperationEnum.GET_FEATURE_INFO.value
 
     @property
     def is_get_feature_request(self) -> bool:
@@ -130,7 +130,7 @@ def is_get_feature_request(self) -> bool:
         :return: true if this is a wfs get feature request
         :rtype: bool
         """
-        return self.operation.lower() == OGCOperationEnum.GET_FEATURE.value.lower()
+        return self.operation == OGCOperationEnum.GET_FEATURE.value
 
     @property
     def is_transaction_request(self) -> bool:
@@ -139,7 +139,7 @@ def is_transaction_request(self) -> bool:
         :return: true if this is a wfs tranasction request
         :rtype: bool
         """
-        return self.operation.lower() == OGCOperationEnum.TRANSACTION.value.lower()
+        return self.operation == OGCOperationEnum.TRANSACTION.value
 
     @property
     def bbox(self) -> GEOSGeometry:
@@ -156,24 +156,16 @@ def bbox(self) -> GEOSGeometry:
         if not self._bbox:
             try:
                 self._bbox = construct_polygon_from_bbox_query_param(
-                    get_dict=self.params_lower)
+                    get_dict=self.ogc_query_params)
             except (MissingBboxParam, MissingServiceParam):
                 # only to avoid error while handling sql in service property
                 self._bbox = GEOSGeometry("POLYGON EMPTY")
         return self._bbox
 
-    @property
-    def params_lower(self) -> Dict:
-        """Lower case key mapper for paramas
-
-        :return: all parameters of the request in lower case key
-        :rtype: Dict
-        """
-        return {k.lower(): v for k, v in self.params.items()} if not self._params_lower else self._params_lower
-
     @property
     def ogc_query_params(self) -> Dict:
         """ Parses the GET parameters into all member variables, which can be found in a ogc request.
+
         :return: all ogc query parameters
         :rtype: Dict
         """
@@ -182,8 +174,18 @@ def ogc_query_params(self) -> Dict:
                           "OUTPUTFORMAT", "SRS", "CRS", "SRSNAME", "WIDTH", "HEIGHT",
                           "TRANSPARENT", "EXCEPTIONS", "BGCOLOR", "TIME", "ELEVATION",
                           "QUERY_LAYERS", "INFO_FORMAT", "FEATURE_COUNT", "I", "J"]
-            self._ogc_query_params = {key: self.params_lower.get(
-                key, self.params_lower.get(key.lower())) for key in query_keys}
+
+            for key in query_keys:
+                value = self.params.get(key, self.params.get(key.lower(), ""))
+
+                if value:
+                    if isinstance(value, list):
+                        # if multiple values are passed in multiple queryparams, we pick the first item
+                        value = value[0]
+
+                    self._ogc_query_params.update({
+                        key: value
+                    })
 
         return self._ogc_query_params
 
diff --git a/tests/models/tests_ogc_request.py b/tests/models/tests_ogc_request.py
index 638cd90..a843bdd 100644
--- a/tests/models/tests_ogc_request.py
+++ b/tests/models/tests_ogc_request.py
@@ -2,6 +2,7 @@
 
 from django.test import RequestFactory, SimpleTestCase
 from eulxml.xmlmap import load_xmlobject_from_file
+
 from ows_lib.models.ogc_request import OGCRequest
 from ows_lib.xml_mapper.xml_requests.wfs.get_feature import GetFeatureRequest
 from tests.settings import DJANGO_TEST_ROOT_DIR
@@ -17,13 +18,14 @@ def test_ogc_request_with_get_map_request(self):
 
         ogc_request: OGCRequest = OGCRequest(
             method="GET",
-            url="/mrmap-proxy/wms/cd16cc1f-3abb-4625-bb96-fbe80dbe23e3/",
-            params={"REQUEST": "GetMap", "SERVICE": "WMS", "VERSION": "1.3.0", "LAYERS": "somelayer,anotherlayer"})
+            url="http://mrmap-proxy/wms/cd16cc1f-3abb-4625-bb96-fbe80dbe23e3/",
+            params={"REQUEST": ["GetMap"], "SERVICE": "WMS", "VERSION": "1.3.0", "LAYERS": "somelayer,anotherlayer"})
 
         self.assertTrue(ogc_request.is_get)
         self.assertTrue(ogc_request.is_get_map_request)
         self.assertEqual(["somelayer", "anotherlayer"],
                          ogc_request.requested_entities)
+        ogc_request.prepare()
 
     def test_ogc_request_with_post_get_feature_request(self):
         """Test that create manager function works correctly for a given GetFeature post request"""
@@ -35,7 +37,7 @@ def test_ogc_request_with_post_get_feature_request(self):
             filename=path, xmlclass=GetFeatureRequest)
 
         ogc_request: OGCRequest = OGCRequest(
-            url="/mrmap-proxy/wfs/73cf78c9-6605-47fd-ac4f-1be59265df65/",
+            url="http://mrmap-proxy/wfs/73cf78c9-6605-47fd-ac4f-1be59265df65/",
             data=get_feature_request.serializeDocument(),
             headers={"content_type": "application/gml+xml; version=3.2"},
             method="POST")
@@ -44,3 +46,4 @@ def test_ogc_request_with_post_get_feature_request(self):
         self.assertTrue(ogc_request.is_get_feature_request)
         self.assertEqual(["ms:Countries"], ogc_request.requested_entities)
         self.assertTrue(isinstance(ogc_request.xml_request, GetFeatureRequest))
+        ogc_request.prepare()