1fb1fd46dSChris Fraire /* 2fb1fd46dSChris Fraire * CDDL HEADER START 3fb1fd46dSChris Fraire * 4fb1fd46dSChris Fraire * The contents of this file are subject to the terms of the 5fb1fd46dSChris Fraire * Common Development and Distribution License (the "License"). 6fb1fd46dSChris Fraire * You may not use this file except in compliance with the License. 7fb1fd46dSChris Fraire * 8fb1fd46dSChris Fraire * See LICENSE.txt included in this distribution for the specific 9fb1fd46dSChris Fraire * language governing permissions and limitations under the License. 10fb1fd46dSChris Fraire * 11fb1fd46dSChris Fraire * When distributing Covered Code, include this CDDL HEADER in each 12fb1fd46dSChris Fraire * file and include the License file at LICENSE.txt. 13fb1fd46dSChris Fraire * If applicable, add the following below this CDDL HEADER, with the 14fb1fd46dSChris Fraire * fields enclosed by brackets "[]" replaced with your own identifying 15fb1fd46dSChris Fraire * information: Portions Copyright [yyyy] [name of copyright owner] 16fb1fd46dSChris Fraire * 17fb1fd46dSChris Fraire * CDDL HEADER END 18fb1fd46dSChris Fraire */ 19fb1fd46dSChris Fraire 20fb1fd46dSChris Fraire /* 21*5d9f3aa0SAdam Hornáček * Copyright (c) 2017, 2019, Chris Fraire <cfraire@me.com>. 22fb1fd46dSChris Fraire */ 23fb1fd46dSChris Fraire package org.opengrok.indexer.util; 24fb1fd46dSChris Fraire 25fb1fd46dSChris Fraire import java.util.regex.Pattern; 26fb1fd46dSChris Fraire 27fb1fd46dSChris Fraire /** 28fb1fd46dSChris Fraire * Represents a container for utility methods concerned with URIs. 29fb1fd46dSChris Fraire */ 30fb1fd46dSChris Fraire public class UriUtils { 31fb1fd46dSChris Fraire 32fb1fd46dSChris Fraire /** 33fb1fd46dSChris Fraire * Represents the immutable return value of 34fb1fd46dSChris Fraire * {@link #trimUri(String, boolean, Pattern)}. 35fb1fd46dSChris Fraire */ 36fb1fd46dSChris Fraire public static final class TrimUriResult { 37fb1fd46dSChris Fraire private final String uri; 38fb1fd46dSChris Fraire private final int pushBackCount; 39fb1fd46dSChris Fraire TrimUriResult(String uri, int pushBackCount)40fb1fd46dSChris Fraire TrimUriResult(String uri, int pushBackCount) { 41fb1fd46dSChris Fraire this.uri = uri; 42fb1fd46dSChris Fraire this.pushBackCount = pushBackCount; 43fb1fd46dSChris Fraire } 44fb1fd46dSChris Fraire getUri()45fb1fd46dSChris Fraire public String getUri() { 46fb1fd46dSChris Fraire return uri; 47fb1fd46dSChris Fraire } 48fb1fd46dSChris Fraire getPushBackCount()49fb1fd46dSChris Fraire public int getPushBackCount() { 50fb1fd46dSChris Fraire return pushBackCount; 51fb1fd46dSChris Fraire } 52fb1fd46dSChris Fraire } 53fb1fd46dSChris Fraire 54fb1fd46dSChris Fraire /** 55fb1fd46dSChris Fraire * Trims a URI, specifying whether to enlist the 56fb1fd46dSChris Fraire * {@link StringUtils#countURIEndingPushback(String)} algorithm or the 57fb1fd46dSChris Fraire * {@link StringUtils#countPushback(String, Pattern)} or both. 58fb1fd46dSChris Fraire * <p> 59fb1fd46dSChris Fraire * If the pushback count is equal to the length of {@code url}, then the 60fb1fd46dSChris Fraire * pushback is set to zero -- in order to avoid a never-ending lexical loop. 61fb1fd46dSChris Fraire * 62fb1fd46dSChris Fraire * @param uri the URI string 63fb1fd46dSChris Fraire * @param shouldCheckEnding a value indicating whether to call 64fb1fd46dSChris Fraire * {@link StringUtils#countURIEndingPushback(String)} 65fb1fd46dSChris Fraire * @param collateralCapture optional pattern to call with 66fb1fd46dSChris Fraire * {@link StringUtils#countPushback(String, Pattern)} 67fb1fd46dSChris Fraire * @return a defined instance 68fb1fd46dSChris Fraire */ trimUri(String uri, boolean shouldCheckEnding, Pattern collateralCapture)69fb1fd46dSChris Fraire public static TrimUriResult trimUri(String uri, boolean shouldCheckEnding, 70fb1fd46dSChris Fraire Pattern collateralCapture) { 71fb1fd46dSChris Fraire 72fb1fd46dSChris Fraire int n = 0; 73fb1fd46dSChris Fraire while (true) { 74fb1fd46dSChris Fraire /* 75fb1fd46dSChris Fraire * An ending-pushback could be present before a collateral capture, 76fb1fd46dSChris Fraire * so detect both in a loop (on a shrinking `url') until no more 77fb1fd46dSChris Fraire * shrinking should occur. 78fb1fd46dSChris Fraire */ 79fb1fd46dSChris Fraire 80fb1fd46dSChris Fraire int subN = 0; 81fb1fd46dSChris Fraire if (shouldCheckEnding) { 82fb1fd46dSChris Fraire subN = StringUtils.countURIEndingPushback(uri); 83fb1fd46dSChris Fraire } 84fb1fd46dSChris Fraire int ccn = StringUtils.countPushback(uri, collateralCapture); 85fb1fd46dSChris Fraire if (ccn > subN) { 86fb1fd46dSChris Fraire subN = ccn; 87fb1fd46dSChris Fraire } 88fb1fd46dSChris Fraire 89fb1fd46dSChris Fraire // Increment if positive, but not if equal to the current length. 90fb1fd46dSChris Fraire if (subN > 0 && subN < uri.length()) { 91fb1fd46dSChris Fraire uri = uri.substring(0, uri.length() - subN); 92fb1fd46dSChris Fraire n += subN; 93fb1fd46dSChris Fraire } else { 94fb1fd46dSChris Fraire break; 95fb1fd46dSChris Fraire } 96fb1fd46dSChris Fraire } 97fb1fd46dSChris Fraire return new TrimUriResult(uri, n); 98fb1fd46dSChris Fraire } 99fb1fd46dSChris Fraire 100fb1fd46dSChris Fraire /** Private to enforce static. */ UriUtils()101fb1fd46dSChris Fraire private UriUtils() { 102fb1fd46dSChris Fraire } 103fb1fd46dSChris Fraire } 104