001/*-
002 * #%L
003 * Smile CDR - CDR
004 * %%
005 * Copyright (C) 2016 - 2026 Smile CDR, Inc.
006 * %%
007 * All rights reserved.
008 * #L%
009 */
010package ca.cdr.test.util;
011
012import jakarta.annotation.Nonnull;
013import jakarta.annotation.Nullable;
014import org.apache.commons.lang3.StringUtils;
015
016/**
017 * Helpers for the URL paths under which Smile CDR modules are served.
018 */
019// Created by Claude Opus 5.5
020public final class UrlPathUtil {
021
022        private UrlPathUtil() {}
023
024        /**
025         * Normalizes a module's {@code context_path} so that it can be appended to a
026         * {@code protocol://host:port} root as-is.
027         *
028         * @param theContextPath the configured context path; {@literal null}, blank and {@code /} all mean
029         *    the root
030         * @return the empty string for the root, otherwise the path with one leading slash and no
031         *    trailing slash, such as {@code /fhir-request}
032         */
033        public static @Nonnull String normalizeContextPath(@Nullable String theContextPath) {
034                String trimmed = StringUtils.strip(StringUtils.trimToEmpty(theContextPath), "/");
035                return trimmed.isEmpty() ? "" : "/" + trimmed;
036        }
037
038        /**
039         * Spring's {@code RestClient} appends a request's URI template to the base URL's path verbatim,
040         * so a base URL with a context path and no trailing slash turns {@code module-config/} into
041         * {@code /admin-jsonmodule-config/}. With the trailing slash, both {@code module-config/} and
042         * {@code /module-config/} resolve beneath the context path.
043         *
044         * @param theBaseUrl a base URL, with or without a trailing slash
045         * @return the same URL ending in exactly one slash
046         */
047        public static @Nonnull String withTrailingSlash(@Nonnull String theBaseUrl) {
048                return theBaseUrl.endsWith("/") ? theBaseUrl : theBaseUrl + "/";
049        }
050}