class BuildModelTransformer implements ModelTransformer {

    public static final String NAMESPACE_PREFIX = "http://maven.apache.org/POM/";

    @Override
    public Model transform(ModelTransformerContext context, Model model, Path path) {
        Model.Builder builder = Model.newBuilder(model);
        handleModelVersion(context, model, path, builder);
        handleParent(context, model, path, builder);
        handleReactorDependencies(context, model, path, builder);
        handleCiFriendlyVersion(context, model, path, builder);
        return builder.build();
    }

    //
    // Infer modelVersion from namespace URI
    //
    void handleModelVersion(ModelTransformerContext context, Model model, Path pomFile, Model.Builder builder) {
        String namespace = model.getNamespaceUri();
        if (model.getModelVersion() == null && namespace != null && namespace.startsWith(NAMESPACE_PREFIX)) {
            builder.modelVersion(namespace.substring(NAMESPACE_PREFIX.length()));
        }
    }

    //
    // Infer parent information
    //
    void handleParent(ModelTransformerContext context, Model model, Path pomFile, Model.Builder builder) {
        Parent parent = model.getParent();
        if (parent != null) {
            String version = parent.getVersion();
            String path = Optional.ofNullable(parent.getRelativePath()).orElse("..");
            if (version == null && !path.isEmpty()) {
                Optional<RelativeProject> resolvedParent = resolveRelativePath(
                        pomFile, context, Paths.get(path), parent.getGroupId(), parent.getArtifactId());
                if (resolvedParent.isPresent()) {
                    version = resolvedParent.get().getVersion();
                }
            }
            // CI Friendly version for parent
            String modVersion = replaceCiFriendlyVersion(context, version);
            builder.parent(parent.withVersion(modVersion));
        }
    }

    //
    // CI friendly versions
    //
    void handleCiFriendlyVersion(ModelTransformerContext context, Model model, Path pomFile, Model.Builder builder) {
        String version = model.getVersion();
        String modVersion = replaceCiFriendlyVersion(context, version);
        builder.version(modVersion);
    }

    //
    // Infer inner reactor dependencies version
    //
    void handleReactorDependencies(ModelTransformerContext context, Model model, Path pomFile, Model.Builder builder) {
        List<Dependency> newDeps = new ArrayList<>();
        boolean modified = false;
        for (Dependency dep : model.getDependencies()) {
            if (dep.getVersion() == null) {
                Model depModel = context.getRawModel(model.getPomFile(), dep.getGroupId(), dep.getArtifactId());
                if (depModel != null) {
                    String v = depModel.getVersion();
                    if (v == null && depModel.getParent() != null) {
                        v = depModel.getParent().getVersion();
                    }
                    dep = dep.withVersion(v);
                    modified = true;
                }
            }
            newDeps.add(dep);
        }
        if (modified) {
            builder.dependencies(newDeps);
        }
    }

    protected String replaceCiFriendlyVersion(ModelTransformerContext context, String version) {
        if (version != null) {
            for (String key : Arrays.asList("changelist", "revision", "sha1")) {
                String val = context.getUserProperty(key);
                if (val != null) {
                    version = version.replace("${" + key + "}", val);
                }
            }
        }
        return version;
    }

    protected Optional<RelativeProject> resolveRelativePath(
            Path pomFile, ModelTransformerContext context, Path relativePath, String groupId, String artifactId) {<FILL_FUNCTION_BODY>}

    private static RelativeProject toRelativeProject(final Model m) {
        String groupId = m.getGroupId();
        if (groupId == null && m.getParent() != null) {
            groupId = m.getParent().getGroupId();
        }

        String version = m.getVersion();
        if (version == null && m.getParent() != null) {
            version = m.getParent().getVersion();
        }

        return new RelativeProject(groupId, m.getArtifactId(), version);
    }

    protected static class RelativeProject {
        private final String groupId;

        private final String artifactId;

        private final String version;

        protected RelativeProject(String groupId, String artifactId, String version) {
            this.groupId = groupId;
            this.artifactId = artifactId;
            this.version = version;
        }

        public String getGroupId() {
            return groupId;
        }

        public String getArtifactId() {
            return artifactId;
        }

        public String getVersion() {
            return version;
        }
    }
}

        Path pomPath = pomFile.resolveSibling(relativePath).normalize();
        if (Files.isDirectory(pomPath)) {
            pomPath = context.locate(pomPath);
        }

        if (pomPath == null || !Files.isRegularFile(pomPath)) {
            return Optional.empty();
        }

        Optional<RelativeProject> mappedProject = Optional.ofNullable(context.getRawModel(pomFile, pomPath.normalize()))
                .map(BuildModelTransformer::toRelativeProject);

        if (mappedProject.isPresent()) {
            RelativeProject project = mappedProject.get();

            if (Objects.equals(groupId, project.getGroupId()) && Objects.equals(artifactId, project.getArtifactId())) {
                return mappedProject;
            }
        }
        return Optional.empty();
    
<no_super_class>