Loads the SAM resources from the given SAM manifest, replaces them with their corresponding
        CloudFormation resources, and returns the resulting CloudFormation template.

        :param dict sam_template: the SAM manifest, as loaded by json.load() or yaml.load(), or as provided by \
                CloudFormation transforms.
        :param dict parameter_values: Map of template parameter names to their values. It is a required parameter that
                should at least be an empty map. By providing an empty map, the caller explicitly opts-into the idea
                that some functionality that relies on resolving parameter references might not work as expected
                (ex: auto-creating new Lambda Version when CodeUri contains reference to template parameter). This is
                why this parameter is required

        :returns: a copy of the template with SAM resources replaced with the corresponding CloudFormation, which may \
                be dumped into a valid CloudFormation JSON or YAML template

def translate(self, sam_template, parameter_values):
        """Loads the SAM resources from the given SAM manifest, replaces them with their corresponding
        CloudFormation resources, and returns the resulting CloudFormation template.

        :param dict sam_template: the SAM manifest, as loaded by json.load() or yaml.load(), or as provided by \
                CloudFormation transforms.
        :param dict parameter_values: Map of template parameter names to their values. It is a required parameter that
                should at least be an empty map. By providing an empty map, the caller explicitly opts-into the idea
                that some functionality that relies on resolving parameter references might not work as expected
                (ex: auto-creating new Lambda Version when CodeUri contains reference to template parameter). This is
                why this parameter is required

        :returns: a copy of the template with SAM resources replaced with the corresponding CloudFormation, which may \
                be dumped into a valid CloudFormation JSON or YAML template
        """
        sam_parameter_values = SamParameterValues(parameter_values)
        sam_parameter_values.add_default_parameter_values(sam_template)
        sam_parameter_values.add_pseudo_parameter_values()
        parameter_values = sam_parameter_values.parameter_values
        # Create & Install plugins
        sam_plugins = prepare_plugins(self.plugins, parameter_values)

        self.sam_parser.parse(
            sam_template=sam_template,
            parameter_values=parameter_values,
            sam_plugins=sam_plugins
        )

        template = copy.deepcopy(sam_template)
        macro_resolver = ResourceTypeResolver(sam_resources)
        intrinsics_resolver = IntrinsicsResolver(parameter_values)
        deployment_preference_collection = DeploymentPreferenceCollection()
        supported_resource_refs = SupportedResourceReferences()
        document_errors = []
        changed_logical_ids = {}

        for logical_id, resource_dict in self._get_resources_to_iterate(sam_template, macro_resolver):
            try:
                macro = macro_resolver\
                    .resolve_resource_type(resource_dict)\
                    .from_dict(logical_id, resource_dict, sam_plugins=sam_plugins)

                kwargs = macro.resources_to_link(sam_template['Resources'])
                kwargs['managed_policy_map'] = self.managed_policy_map
                kwargs['intrinsics_resolver'] = intrinsics_resolver
                kwargs['deployment_preference_collection'] = deployment_preference_collection
                translated = macro.to_cloudformation(**kwargs)

                supported_resource_refs = macro.get_resource_references(translated, supported_resource_refs)

                # Some resources mutate their logical ids. Track those to change all references to them:
                if logical_id != macro.logical_id:
                    changed_logical_ids[logical_id] = macro.logical_id

                del template['Resources'][logical_id]
                for resource in translated:
                    if verify_unique_logical_id(resource, sam_template['Resources']):
                        template['Resources'].update(resource.to_dict())
                    else:
                        document_errors.append(DuplicateLogicalIdException(
                            logical_id, resource.logical_id, resource.resource_type))
            except (InvalidResourceException, InvalidEventException) as e:
                document_errors.append(e)

        if deployment_preference_collection.any_enabled():
            template['Resources'].update(deployment_preference_collection.codedeploy_application.to_dict())

            if not deployment_preference_collection.can_skip_service_role():
                template['Resources'].update(deployment_preference_collection.codedeploy_iam_role.to_dict())

            for logical_id in deployment_preference_collection.enabled_logical_ids():
                template['Resources'].update(deployment_preference_collection.deployment_group(logical_id).to_dict())

        # Run the after-transform plugin target
        try:
            sam_plugins.act(LifeCycleEvents.after_transform_template, template)
        except (InvalidDocumentException, InvalidResourceException) as e:
            document_errors.append(e)

        # Cleanup
        if 'Transform' in template:
            del template['Transform']

        if len(document_errors) == 0:
            template = intrinsics_resolver.resolve_sam_resource_id_refs(template, changed_logical_ids)
            template = intrinsics_resolver.resolve_sam_resource_refs(template, supported_resource_refs)
            return template
        else:
            raise InvalidDocumentException(document_errors)