001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.doxia.util; 020 021/** 022 * Utility methods for string operations. 023 * This class provides methods that were previously supplied by Apache Commons Lang3. 024 * 025 * @since 2.1.0 026 */ 027public class DoxiaStringUtils { 028 029 private DoxiaStringUtils() { 030 // utility class 031 } 032 033 /** 034 * Repeats a string a certain number of times. 035 * 036 * @param str the string to repeat 037 * @param repeat number of times to repeat 038 * @return the repeated string 039 */ 040 public static String repeat(String str, int repeat) { 041 if (str == null) { 042 return null; 043 } 044 if (repeat <= 0) { 045 return ""; 046 } 047 // Check for potential overflow 048 int len = str.length(); 049 if (len > 0 && repeat > Integer.MAX_VALUE / len) { 050 throw new IllegalArgumentException("Resulting string would be too long"); 051 } 052 StringBuilder sb = new StringBuilder(len * repeat); 053 for (int i = 0; i < repeat; i++) { 054 sb.append(str); 055 } 056 return sb.toString(); 057 } 058 059 /** 060 * Replaces all occurrences of a string within another string. 061 * 062 * @param text the text to search and replace in 063 * @param searchString the string to search for 064 * @param replacement the string to replace with 065 * @return the text with any replacements processed 066 */ 067 public static String replace(String text, String searchString, String replacement) { 068 if (text == null || text.isEmpty() || searchString == null || searchString.isEmpty()) { 069 return text; 070 } 071 if (replacement == null) { 072 replacement = ""; 073 } 074 return text.replace(searchString, replacement); 075 } 076 077 /** 078 * Checks if a string is not empty. 079 * 080 * @param str the string to check 081 * @return true if the string is not null and not empty 082 */ 083 public static boolean isNotEmpty(String str) { 084 return str != null && !str.isEmpty(); 085 } 086 087 /** 088 * Checks if a string is blank (null, empty, or whitespace only). 089 * 090 * @param str the string to check 091 * @return true if the string is null, empty, or whitespace only 092 */ 093 public static boolean isBlank(String str) { 094 if (str == null || str.isEmpty()) { 095 return true; 096 } 097 for (int i = 0; i < str.length(); i++) { 098 if (!Character.isWhitespace(str.charAt(i))) { 099 return false; 100 } 101 } 102 return true; 103 } 104 105 /** 106 * Checks if all strings are blank. 107 * 108 * @param strs the strings to check 109 * @return true if all strings are blank 110 */ 111 public static boolean isAllBlank(String... strs) { 112 if (strs == null || strs.length == 0) { 113 return true; 114 } 115 for (String str : strs) { 116 if (!isBlank(str)) { 117 return false; 118 } 119 } 120 return true; 121 } 122 123 /** 124 * Splits a string by specified delimiters. 125 * 126 * @param str the string to split 127 * @param separatorChars the characters to use as delimiters 128 * @return an array of parsed strings, empty array if null string input 129 */ 130 public static String[] split(String str, String separatorChars) { 131 if (str == null) { 132 return new String[0]; 133 } 134 if (str.isEmpty()) { 135 return new String[0]; 136 } 137 if (separatorChars == null || separatorChars.isEmpty()) { 138 separatorChars = " \t\n\r\f"; 139 } 140 141 java.util.List<String> result = new java.util.ArrayList<>(); 142 int start = 0; 143 int len = str.length(); 144 145 while (start < len) { 146 // Skip separators 147 while (start < len && separatorChars.indexOf(str.charAt(start)) >= 0) { 148 start++; 149 } 150 if (start >= len) { 151 break; 152 } 153 // Find end of token 154 int end = start; 155 while (end < len && separatorChars.indexOf(str.charAt(end)) < 0) { 156 end++; 157 } 158 result.add(str.substring(start, end)); 159 start = end; 160 } 161 162 return result.toArray(new String[0]); 163 } 164 165 /** 166 * Removes a substring only if it is at the end of a source string. 167 * 168 * @param str the source string 169 * @param remove the string to remove 170 * @return the substring with the string removed if found 171 */ 172 public static String removeEnd(String str, String remove) { 173 if (str == null || remove == null || str.isEmpty() || remove.isEmpty()) { 174 return str; 175 } 176 if (str.endsWith(remove)) { 177 return str.substring(0, str.length() - remove.length()); 178 } 179 return str; 180 } 181 182 /** 183 * Strips any of a set of characters from the start of a string. 184 * 185 * @param str the string to remove characters from 186 * @param stripChars the characters to remove 187 * @return the stripped string 188 */ 189 public static String stripStart(String str, String stripChars) { 190 if (str == null || str.isEmpty()) { 191 return str; 192 } 193 int start = 0; 194 int len = str.length(); 195 if (stripChars == null) { 196 while (start < len && Character.isWhitespace(str.charAt(start))) { 197 start++; 198 } 199 } else { 200 while (start < len && stripChars.indexOf(str.charAt(start)) >= 0) { 201 start++; 202 } 203 } 204 return start > 0 ? str.substring(start) : str; 205 } 206 207 /** 208 * Counts how many times the substring appears in the larger string. 209 * 210 * @param str the string to check 211 * @param sub the substring to count 212 * @return the number of occurrences, 0 if either string is null 213 */ 214 public static int countMatches(String str, String sub) { 215 if (str == null || str.isEmpty() || sub == null || sub.isEmpty()) { 216 return 0; 217 } 218 int count = 0; 219 int idx = 0; 220 while ((idx = str.indexOf(sub, idx)) != -1) { 221 count++; 222 idx += sub.length(); 223 } 224 return count; 225 } 226}