class StringVisitorModelInterpolator extends AbstractStringBasedModelInterpolator {
    @Inject
    public StringVisitorModelInterpolator(
            PathTranslator pathTranslator, UrlNormalizer urlNormalizer, RootLocator rootLocator) {
        super(pathTranslator, urlNormalizer, rootLocator);
    }

    interface InnerInterpolator {
        String interpolate(String value);
    }

    @Deprecated
    @Override
    public Model interpolateModel(
            Model model, File projectDir, ModelBuildingRequest config, ModelProblemCollector problems) {
        return interpolateModel(model, projectDir != null ? projectDir.toPath() : null, config, problems);
    }

    @Override
    public Model interpolateModel(
            Model model, Path projectDir, ModelBuildingRequest config, ModelProblemCollector problems) {<FILL_FUNCTION_BODY>}

    private InnerInterpolator createInterpolator(
            List<? extends ValueSource> valueSources,
            List<? extends InterpolationPostProcessor> postProcessors,
            final ModelProblemCollector problems,
            ModelBuildingRequest config) {
        final Map<String, String> cache = new HashMap<>();
        final StringSearchInterpolator interpolator = new StringSearchInterpolator();
        interpolator.setCacheAnswers(true);
        for (ValueSource vs : valueSources) {
            interpolator.addValueSource(vs);
        }
        for (InterpolationPostProcessor postProcessor : postProcessors) {
            interpolator.addPostProcessor(postProcessor);
        }
        final RecursionInterceptor recursionInterceptor = createRecursionInterceptor(config);
        return value -> {
            if (value != null && value.contains("${")) {
                String c = cache.get(value);
                if (c == null) {
                    try {
                        c = interpolator.interpolate(value, recursionInterceptor);
                    } catch (InterpolationException e) {
                        problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
                                .setMessage(e.getMessage())
                                .setException(e));
                    }
                    cache.put(value, c);
                }
                return c;
            }
            return value;
        };
    }
}

        List<? extends ValueSource> valueSources = createValueSources(model, projectDir, config, problems);
        List<? extends InterpolationPostProcessor> postProcessors = createPostProcessors(model, projectDir, config);

        InnerInterpolator innerInterpolator = createInterpolator(valueSources, postProcessors, problems, config);

        return new MavenTransformer(innerInterpolator::interpolate).visit(model);
    
<methods>public void <init>(org.apache.maven.model.path.PathTranslator, org.apache.maven.model.path.UrlNormalizer, org.apache.maven.model.root.RootLocator) ,public org.apache.maven.model.Model interpolateModel(org.apache.maven.model.Model, java.io.File, org.apache.maven.model.building.ModelBuildingRequest, org.apache.maven.model.building.ModelProblemCollector) ,public org.apache.maven.model.Model interpolateModel(org.apache.maven.model.Model, java.nio.file.Path, org.apache.maven.model.building.ModelBuildingRequest, org.apache.maven.model.building.ModelProblemCollector) <variables>private static final java.lang.String PREFIX_POM,private static final java.lang.String PREFIX_PROJECT,private static final List<java.lang.String> PROJECT_PREFIXES_3_1,private static final List<java.lang.String> PROJECT_PREFIXES_4_0,private static final non-sealed Collection<java.lang.String> TRANSLATED_PATH_EXPRESSIONS,private final non-sealed org.apache.maven.model.path.PathTranslator pathTranslator,private final non-sealed org.apache.maven.model.root.RootLocator rootLocator,private final non-sealed org.apache.maven.model.path.UrlNormalizer urlNormalizer