001/*
002 * Copyright 2023 the original author or authors.
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * https://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.cuioss.tools.net;
017
018import static de.cuioss.tools.string.MoreStrings.isEmpty;
019
020import java.net.URI;
021import java.net.URISyntaxException;
022import java.util.Collections;
023import java.util.List;
024import java.util.Optional;
025
026import de.cuioss.tools.logging.CuiLogger;
027import de.cuioss.tools.string.MoreStrings;
028import de.cuioss.tools.string.Splitter;
029import lombok.experimental.UtilityClass;
030
031/**
032 * Provides some utility methods for url / path related data
033 *
034 * @author Oliver Wolff
035 *
036 */
037@UtilityClass
038public final class UrlHelper {
039
040    private static final CuiLogger LOGGER = new CuiLogger(UrlHelper.class);
041
042    /**
043     * @param url to be adapted
044     * @return the given url if it already suffixed with '/' or null / empty. The
045     *         given url suffixed with '/' otherwise
046     */
047    public static String addTrailingSlashToUrl(String url) {
048        if (isEmpty(url) || url.endsWith("/")) {
049            return url;
050        }
051        return url + "/";
052    }
053
054    /**
055     * @param url to be adapted
056     * @return the given url if it is not suffixed with '/' or null / empty. The
057     *         given url '/' removed otherwise. Multiple trailing slashes will be
058     *         removed as well
059     */
060    public static String removeTrailingSlashesFromUrl(String url) {
061        if (isEmpty(url) || !url.endsWith("/")) {
062            return url;
063        }
064        return removeTrailingSlashesFromUrl(url.substring(0, url.length() - 1));
065    }
066
067    /**
068     * @param path to be adapted
069     * @return the given path if it already prefixed with '/'. The given path
070     *         prefixed with '/' otherwise. In case of being null or empty it will
071     *         return "/"
072     */
073    public static String addPrecedingSlashToPath(String path) {
074        if (isEmpty(path)) {
075            return "/";
076        }
077        if (path.startsWith("/")) {
078            return path;
079        }
080        return "/" + path;
081    }
082
083    /**
084     * @param path
085     * @return the given path if it is not suffixed with '/' or null / empty. The
086     *         given path '/' removed otherwise. Multiple preceding slashes will be
087     *         removed as well
088     */
089    public static String removePrecedingSlashFromPath(String path) {
090        if (isEmpty(path) || !path.startsWith("/")) {
091            return path;
092        }
093        return removePrecedingSlashFromPath(path.substring(1));
094    }
095
096    /**
097     * Split the given path String in a unified view with a list of {@link String}.
098     * The individual path-elements are implicitly trimmed
099     *
100     * @param pathString if it is null or empty an empty List will be returned
101     * @return the list view on the path elements. never null but may be empty
102     */
103    public static List<String> splitPath(String pathString) {
104        if (isEmpty(pathString)) {
105            return Collections.emptyList();
106        }
107        return Splitter.on("/").trimResults().omitEmptyStrings().splitToList(pathString);
108    }
109
110    /**
111     * @param uri value to be verified if it is a valid URI.
112     * @return URI object, if the given value is a valid URI.
113     */
114    public Optional<URI> tryParseUri(final String uri) {
115        if (!MoreStrings.isEmpty(uri)) {
116            try {
117                return Optional.of(new URI(uri));
118            } catch (URISyntaxException e) {
119                LOGGER.trace(e, "Invalid URI");
120            }
121        }
122        return Optional.empty();
123    }
124
125    /**
126     * @param uri value to be verified if it is a valid URI.
127     * @return true, if the given value is a valid URI. False otherwise.
128     */
129    public boolean isValidUri(final String uri) {
130        if (!MoreStrings.isEmpty(uri)) {
131            try {
132                new URI(uri);
133            } catch (URISyntaxException e) {
134                return false;
135            }
136        }
137        return true;
138    }
139}