Utility method to convert some value into the desired type. It relies on get_all_conversion_chains to find the
        converters, and apply them in correct order
        :return:

def find_and_convert(self, attr_name: str, attr_value: S, desired_attr_type: Type[T], logger: Logger,
                         options: Dict[str, Dict[str, Any]]) -> T:
        """
        Utility method to convert some value into the desired type. It relies on get_all_conversion_chains to find the
        converters, and apply them in correct order
        :return:
        """

        if robust_isinstance(attr_value, desired_attr_type) and not is_collection(desired_attr_type):
            # value is already of the correct type
            return attr_value

        else:
            # try to find conversion chains
            generic, approx, exact = self.get_all_conversion_chains(type(attr_value), desired_attr_type)
            all_chains = generic + approx + exact

            if len(all_chains) > 0:
                all_errors = dict()
                for chain in reversed(all_chains):
                    try:
                        return chain.convert(desired_attr_type, attr_value, logger, options)
                    except Exception as e:
                        all_errors[chain] = e
                raise AttrConversionException.create(attr_name, attr_value, desired_attr_type, all_errors)

            else:
                # did not find any conversion chain
                raise NoConverterFoundForObjectType.create(self, attr_value, desired_attr_type)