def test_handle_ellipse(self, mock_outer, mock_cov, mock_def_route):

        # Mock for apply_policy_settings.
        mock_outer.find_service_for_ellipse = MagicMock()
        expected = lostservice.model.responses.FindServiceResponse()
        mock_outer.find_service_for_ellipse.return_value = {
            'response': expected
        }

        mock_cov.check_coverage = MagicMock()
        mock_cov.check_coverage.return_value = 'some.server.name'

        mock_def_route.check_default_route = MagicMock()
        mock_def_route.check_default_route.side_effect = \
            NotFoundException('The server could not find an answer to the query.')

        target = lostservice.handling.core.FindServiceHandler(
            mock_outer, mock_cov, mock_def_route)

        model = lostservice.model.requests.FindServiceRequest()
        model.location = lostservice.model.location.Location()
        model.location.location = lostservice.model.geodetic.Ellipse()

        with self.assertRaises(NotFoundException) as context:
            actual = target.handle_request(model, {})
            mock_outer.find_service_for_ellipse.assert_called_once()
            mock_outer.find_service_for_ellipse.assert_called_with(model)
            self.assertTrue('The server could not find an answer to the query.'
                            in str(context.exception))
            self.assertTrue(actual is expected,
                            'Response did not match expected value.')
Beispiel #2
0
    def handle_request(self, request, context):
        """
        Entry point for request handling.

        :param request: The request
        :type request: A subclass of :py:class:`ListServicesByLocationRequest`
        :param context: The request context.
        :type context: ``dict``
        :return: The response.
        :rtype: :py:class:`ListServicesByLocationResponse`
        """
        try:
            self.check_coverage(request.location.location)
        except Exception:
            raise

        response = None
        if type(request.location.location) is Point:
            response = self._outer.list_services_by_location_for_point(request)
        elif type(request.location.location) is Circle:
            response = self._outer.list_services_by_location_for_circle(
                request)
        elif type(request.location.location) is Ellipse:
            response = self._outer.list_services_by_location_for_ellipse(
                request)
        elif type(request.location.location) is Arcband:
            response = self._outer.list_service_by_location_for_arcband(
                request)
        elif type(request.location.location) is Polygon:
            response = self._outer.list_services_by_location_for_polygon(
                request)
        elif type(request.location.location) is CivicAddress:
            response = self._outer.list_services_by_location_for_civicaddress(
                request)
        else:
            logger.error('Invalid location type.')
            raise BadRequestException('Invalid location type.')
        if response is not None:
            logger.debug('Response found!')
            return_value = {
                'response': response['response'],
                'latitude': response['latitude'],
                'longitude': response['longitude']
            }
            return return_value
        else:
            logger.error(
                f'Unable to find an answer to the query for {request.location.location}.'
            )
            raise NotFoundException(
                'The server could not find an answer to the query.')
    def check_default_route(self, request):
        """
        Check if there is a default route for the passed in request
        :param request: a Find Service Request
        :type request FindServiceRequest
        :return: The mapping if there is a default found
        """

        # Check for default routes
        # if there are none then throw a NotFoundException (return a notFound LoST error)
        default_route_uri = None
        if type(request.location.location) is CivicAddress:
            default_route_uri = self._get_default_civic_route(request)
        else:
            default_route_uri = self._get_default_route(request)

        if default_route_uri is None:
            logger.warning(
                f'No default route URI found for URN: {request.service}')
            raise NotFoundException(
                'The server could not find an answer to the query.')
        else:
            logger.debug(f'Using default route URI: {default_route_uri}')
            # Create a default mapping given just a uri
            new_dict = {
                'serviceurn': request.service,
                'routeuri': default_route_uri,
                'displayname': '',
                'srcunqid': str(uuid.uuid4()),
                'servicenum': '',
                'updatedate': str(datetime.datetime.utcnow()),
                'default_route_used': True
            }

            default_mapping = [new_dict]

            return default_mapping
Beispiel #4
0
    def handle_request(self, request, context):
        """
        Entry point for request handling.

        :param request: The request
        :type request: A subclass of :py:class:`FindServiceRequest`
        :param context: The request context.
        :type context: ``dict``
        :return: The response.
        :rtype: :py:class:`FindServiceResponse`
        """

        try:
            self.check_coverage(request.location.location)
        except Exception:
            raise

        try:
            response = None
            if type(request.location.location) is Point:
                response = self._outer.find_service_for_point(request)
            elif type(request.location.location) is Circle:
                response = self._outer.find_service_for_circle(request)
            elif type(request.location.location) is Ellipse:
                response = self._outer.find_service_for_ellipse(request)
            elif type(request.location.location) is Arcband:
                response = self._outer.find_service_for_arcband(request)
            elif type(request.location.location) is Polygon:
                response = self._outer.find_service_for_polygon(request)
            elif type(request.location.location) is CivicAddress:
                response = self._outer.find_service_for_civicaddress(request)
            else:
                logger.error('Invalid location type.')
                raise BadRequestException('Invalid location type.')
        except NotFoundException:
            if type(request.location.location) is CivicAddress:
                # check if default route exists, if not raise the same exception
                mapping = self._default_route_handler.check_default_route(
                    request)
                # build the response with this mapping
                outer_response = self._outer._build_response(
                    [], request.location.id, mapping, request.nonlostdata)
                response = {
                    'response': outer_response,
                    'latitude': 0.0,
                    'longitude': 0.0
                }
            else:
                raise NotFoundException(
                    'The server could not find an answer to the query.')
        return_value = {}
        # If it's not a CivicAddress and there are no mappings, then check for a default route.
        # Unlike FindCivic which throws an exception if it can't find a resolution, geodetic
        # requests return nothing for the mapping an empty list
        if type(request.location.location) is not CivicAddress and \
                (response['response'].mappings is None or len(response['response'].mappings) == 0):
            # the following function can throw a NotFoundException, In that case since we've exhausted all
            # tries we let it get caught by execute_query in app.py (which returns a not found message)
            mapping = self._default_route_handler.check_default_route(request)
            # build the response with this mapping
            response['response'] = self._outer._build_response(
                [], request.location.id, mapping, request.nonlostdata)

        return_value['latitude'] = response['latitude']
        return_value['longitude'] = response['longitude']

        return_value['response'] = response['response']

        return return_value
    def run_civic_location_search(self, locator, offset_distance,
                                  civic_request):
        """
        Creates a dictionary of values to pass into the civvy library to run civic address match queries.
        :param locator:
        :param offset_distance: the distance to offset the resultant point of an RCL match.
        :param civic_request: int
        :return: a collection of results from the civic location queries.
        """

        # Make sure we have a locator to use first.
        if locator is not None:
            civvy_obj = civic_request.location.location
            # Create dictionary of values from request into a civic location dictionary for civvy to use.
            civic_dict = {}
            civic_dict['country'] = civvy_obj.country
            if civvy_obj.a1:
                civic_dict['a1'] = civvy_obj.a1
            if civvy_obj.a2:
                civic_dict['a2'] = civvy_obj.a2
            if civvy_obj.a3:
                civic_dict['a3'] = civvy_obj.a3
            if civvy_obj.a4:
                civic_dict['a4'] = civvy_obj.a4
            if civvy_obj.a5:
                civic_dict['a5'] = civvy_obj.a5
            if civvy_obj.a6:
                civic_dict['a6'] = civvy_obj.a6
            if civvy_obj.rd:
                civic_dict['rd'] = civvy_obj.rd
            if civvy_obj.pod:
                civic_dict['pod'] = civvy_obj.pod
            if civvy_obj.sts:
                civic_dict['sts'] = civvy_obj.sts
            if civvy_obj.hno:
                civic_dict['hno'] = civvy_obj.hno
            if civvy_obj.hns:
                civic_dict['hns'] = civvy_obj.hns
            if civvy_obj.lmk:
                civic_dict['lmk'] = civvy_obj.lmk
            if civvy_obj.loc:
                civic_dict['loc'] = civvy_obj.loc
            if civvy_obj.flr:
                civic_dict['flr'] = civvy_obj.flr
            if civvy_obj.nam:
                civic_dict['nam'] = civvy_obj.nam
            if civvy_obj.pc:
                civic_dict['pc'] = civvy_obj.pc
            if civvy_obj.pom:
                civic_dict['pom'] = civvy_obj.pom
            if civvy_obj.hnp:
                civic_dict['hnp'] = civvy_obj.hnp
            if civvy_obj.lmkp:
                civic_dict['lmkp'] = civvy_obj.lmkp
            if civvy_obj.mp:
                civic_dict['mp'] = civvy_obj.mp

            # We can create several civic addresses and pass them to the locator.
            civic_address = CivicAddress(**civic_dict)
            logger.info('Executing civic address query')
            # Let's get the results for this civic address.
            logger.debug(
                'Running civic address query for list services through civvy.')
            locator_results = locator.locate_civic_address(
                civic_address=civic_address, offset_distance=offset_distance)

            return locator_results
        else:
            # Who did this, and why are you doing it?!
            logger.error('Locator object not passed.')
            raise NotFoundException(
                'Locator not defined, cannot complete civic address request.',
                None)
            return None
Beispiel #6
0
    def format(self, data):
        """
        Formats a findService LoST response.

        :param data: The response to be formatted.
        :type data: :py:class:`FindServiceResponse`
        :return: The formatted output.
        :rtype: :py:class:`_ElementTree`
        """
        if data.mappings is None or len(data.mappings) == 0:
            logger.warning('Could not find an answer to the request.', None)
            raise NotFoundException('Could not find an answer to the request.',
                                    None)

        # create the root element of the xml response.
        xml_response = lxml.etree.Element('findServiceResponse',
                                          nsmap={
                                              None: LOST_URN,
                                              GML_PREFIX: GML_URN
                                          })
        for item in data.mappings:
            # Add mapping sub element
            mapping = lxml.etree.SubElement(xml_response,
                                            'mapping',
                                            attrib={
                                                'expires':
                                                item.expires,
                                                'lastUpdated':
                                                str(item.last_updated),
                                                'source':
                                                item.source,
                                                'sourceId':
                                                item.source_id
                                            })

            # add the displayname, serviceurn, routeuri, servicenum to mapping
            services_element = lxml.etree.SubElement(mapping, 'service')
            services_element.text = item.service_urn
            if type(item) is ResponseMapping:
                services_element = lxml.etree.SubElement(
                    mapping, 'displayName')
                services_element.text = item.display_name

                attr = services_element.attrib
                attr['{http://www.w3.org/XML/1998/namespace}lang'] = 'en'

                services_element = lxml.etree.SubElement(mapping, 'uri')
                services_element.text = item.route_uri

                services_element = lxml.etree.SubElement(
                    mapping, 'serviceNumber')
                services_element.text = item.service_number

                # if boundary_value = None do not add serviceBoundary tag to the response (override setting)
                # if boundary_value = "" then include serviceBoundaryReference tag
                # if boundary_value contains value then include serviceBoundary tag
                if item.boundary_value is not None:
                    if item.boundary_value == "":
                        attr_element = collections.OrderedDict()
                        attr_element['source'] = item.source
                        attr_element['key'] = item.source_id
                        lxml.etree.SubElement(mapping,
                                              'serviceBoundaryReference',
                                              attrib=attr_element)
                    else:
                        # TODO - fix the profile.
                        services_element = lxml.etree.SubElement(
                            mapping, 'serviceBoundary', profile='geodetic-2d')

                        final_gml_as_xml = io.StringIO(
                            '''<root xmlns:gml="{0}">{1}</root>'''.format(
                                GML_URN, item.boundary_value))
                        final_gml = etree.parse(final_gml_as_xml).getroot()
                        services_element.extend(final_gml)

            elif type(item) is AdditionalDataResponseMapping:
                services_element = lxml.etree.SubElement(mapping, 'uri')
                services_element.text = item.adddatauri

            if hasattr(item, "locationValidation"):
                # add the validation element
                validation_element = lxml.etree.SubElement(
                    xml_response, 'locationValidation')
                if item.locationValidation.get("valid"):
                    valid_element = lxml.etree.SubElement(
                        validation_element, 'valid')
                    valid_element.text = item.locationValidation.get("valid")
                if item.locationValidation.get("invalid"):
                    invalid_element = lxml.etree.SubElement(
                        validation_element, 'invalid')
                    invalid_element.text = item.locationValidation.get(
                        "invalid")
                if item.locationValidation.get("unchecked"):
                    unchecked_element = lxml.etree.SubElement(
                        validation_element, 'unchecked')
                    unchecked_element.text = item.locationValidation.get(
                        "unchecked")

        # add the path element
        path_element = lxml.etree.SubElement(xml_response, 'path')

        # not generate a 'via' element for each source.
        if data.path is not None:
            for a_path in data.path:
                via_element = lxml.etree.SubElement(path_element,
                                                    'via',
                                                    attrib={'source': a_path})

        lxml.etree.SubElement(xml_response,
                              'locationUsed',
                              attrib={'id': data.location_used})

        # Add NonLoSTdata items into response (pass though items)
        for nonlost_item in data.nonlostdata:
            xml_response.append(nonlost_item)

        return xml_response