1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.vfs2.filter; 18 19 import java.io.File; 20 21 /** 22 * Enumeration of IO case sensitivity. 23 * <p> 24 * Different filing systems have different rules for case-sensitivity. Windows 25 * is case-insensitive, Unix is case-sensitive. 26 * </p> 27 * <p> 28 * This class captures that difference, providing an enumeration to control how 29 * file name comparisons should be performed. It also provides methods that use 30 * the enumeration to perform comparisons. 31 * </p> 32 * <p> 33 * Wherever possible, you should use the {@code check} methods in this 34 * class to compare file names. 35 * </p> 36 * 37 * @author This code was originally ported from Apache Commons IO File Filter 38 * @see "http://commons.apache.org/proper/commons-io/" 39 * @since 2.4 40 */ 41 public enum IOCase { 42 43 /** 44 * The constant for case sensitive regardless of operating system. 45 */ 46 SENSITIVE("Sensitive", true), 47 48 /** 49 * The constant for case insensitive regardless of operating system. 50 */ 51 INSENSITIVE("Insensitive", false), 52 53 /** 54 * The constant for case sensitivity determined by the current operating system. 55 * Windows is case-insensitive when comparing file names, Unix is case-sensitive. 56 * <p> 57 * <strong>Note:</strong> This only caters for Windows and Unix. Other operating 58 * systems (e.g. OSX and OpenVMS) are treated as case sensitive if they use the 59 * Unix file separator and case-insensitive if they use the Windows file 60 * separator (see {@link java.io.File#separatorChar}). 61 * <p> 62 * If you serialize this constant on Windows, and deserialize on Unix, or vice 63 * versa, then the value of the case-sensitivity flag will change. 64 */ 65 SYSTEM("System", !(File.separatorChar == '\\')); 66 67 /** Serialization version. */ 68 private static final long serialVersionUID = -6343169151696340687L; 69 70 /** The enumeration name. */ 71 private final String name; 72 73 /** The sensitivity flag. */ 74 private final transient boolean sensitive; 75 76 // ----------------------------------------------------------------------- 77 /** 78 * Factory method to create an IOCase from a name. 79 * 80 * @param name the name to find 81 * @return the IOCase object 82 * @throws IllegalArgumentException if the name is invalid 83 */ 84 public static IOCase forName(final String name) { 85 for (final IOCase ioCase : IOCase.values()) { 86 if (ioCase.getName().equals(name)) { 87 return ioCase; 88 } 89 } 90 throw new IllegalArgumentException("Invalid IOCase name: " + name); 91 } 92 93 // ----------------------------------------------------------------------- 94 /** 95 * Constructs a new instance. 96 * 97 * @param name the name 98 * @param sensitive the sensitivity 99 */ 100 IOCase(final String name, final boolean sensitive) { 101 this.name = name; 102 this.sensitive = sensitive; 103 } 104 105 /** 106 * Replaces the enumeration from the stream with a real one. This ensures that 107 * the correct flag is set for SYSTEM. 108 * 109 * @return the resolved object 110 */ 111 private Object readResolve() { 112 return forName(name); 113 } 114 115 // ----------------------------------------------------------------------- 116 /** 117 * Gets the name of the constant. 118 * 119 * @return the name of the constant 120 */ 121 public String getName() { 122 return name; 123 } 124 125 /** 126 * Does the object represent case sensitive comparison. 127 * 128 * @return true if case sensitive 129 */ 130 public boolean isCaseSensitive() { 131 return sensitive; 132 } 133 134 // ----------------------------------------------------------------------- 135 /** 136 * Compares two strings using the case-sensitivity rule. 137 * <p> 138 * This method mimics {@link String#compareTo} but takes case-sensitivity into 139 * account. 140 * 141 * @param str1 the first string to compare, not null 142 * @param str2 the second string to compare, not null 143 * @return true if equal using the case rules 144 * @throws NullPointerException if either string is null 145 */ 146 public int checkCompareTo(final String str1, final String str2) { 147 if (str1 == null || str2 == null) { 148 throw new NullPointerException("The strings must not be null"); 149 } 150 return sensitive ? str1.compareTo(str2) : str1.compareToIgnoreCase(str2); 151 } 152 153 /** 154 * Compares two strings using the case-sensitivity rule. 155 * <p> 156 * This method mimics {@link String#equals} but takes case-sensitivity into 157 * account. 158 * 159 * @param str1 the first string to compare, not null 160 * @param str2 the second string to compare, not null 161 * @return true if equal using the case rules 162 * @throws NullPointerException if either string is null 163 */ 164 public boolean checkEquals(final String str1, final String str2) { 165 if (str1 == null || str2 == null) { 166 throw new NullPointerException("The strings must not be null"); 167 } 168 return sensitive ? str1.equals(str2) : str1.equalsIgnoreCase(str2); 169 } 170 171 /** 172 * Checks if one string starts with another using the case-sensitivity rule. 173 * <p> 174 * This method mimics {@link String#startsWith(String)} but takes 175 * case-sensitivity into account. 176 * 177 * @param str the string to check, not null 178 * @param start the start to compare against, not null 179 * @return true if equal using the case rules 180 * @throws NullPointerException if either string is null 181 */ 182 public boolean checkStartsWith(final String str, final String start) { 183 return str.regionMatches(!sensitive, 0, start, 0, start.length()); 184 } 185 186 /** 187 * Checks if one string ends with another using the case-sensitivity rule. 188 * <p> 189 * This method mimics {@link String#endsWith} but takes case-sensitivity into 190 * account. 191 * 192 * @param str the string to check, not null 193 * @param end the end to compare against, not null 194 * @return true if equal using the case rules 195 * @throws NullPointerException if either string is null 196 */ 197 public boolean checkEndsWith(final String str, final String end) { 198 final int endLen = end.length(); 199 return str.regionMatches(!sensitive, str.length() - endLen, end, 0, endLen); 200 } 201 202 /** 203 * Checks if one string contains another starting at a specific index using the 204 * case-sensitivity rule. 205 * <p> 206 * This method mimics parts of {@link String#indexOf(String, int)} but takes 207 * case-sensitivity into account. 208 * 209 * @param str the string to check, not null 210 * @param strStartIndex the index to start at in str 211 * @param search the start to search for, not null 212 * @return the first index of the search String, -1 if no match or {@code null} 213 * string input 214 * @throws NullPointerException if either string is null 215 * @since 2.0 216 */ 217 public int checkIndexOf(final String str, final int strStartIndex, final String search) { 218 final int endIndex = str.length() - search.length(); 219 if (endIndex >= strStartIndex) { 220 for (int i = strStartIndex; i <= endIndex; i++) { 221 if (checkRegionMatches(str, i, search)) { 222 return i; 223 } 224 } 225 } 226 return -1; 227 } 228 229 /** 230 * Checks if one string contains another at a specific index using the 231 * case-sensitivity rule. 232 * <p> 233 * This method mimics parts of 234 * {@link String#regionMatches(boolean, int, String, int, int)} but takes 235 * case-sensitivity into account. 236 * 237 * @param str the string to check, not null 238 * @param strStartIndex the index to start at in str 239 * @param search the start to search for, not null 240 * @return true if equal using the case rules 241 * @throws NullPointerException if either string is null 242 */ 243 public boolean checkRegionMatches(final String str, final int strStartIndex, final String search) { 244 return str.regionMatches(!sensitive, strStartIndex, search, 0, search.length()); 245 } 246 247 // ----------------------------------------------------------------------- 248 /** 249 * Gets a string describing the sensitivity. 250 * 251 * @return a string describing the sensitivity 252 */ 253 @Override 254 public String toString() { 255 return name; 256 } 257 258 }