001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.io; 018 019import java.io.Serializable; 020 021/** 022 * Enumeration of IO case sensitivity. 023 * <p> 024 * Different filing systems have different rules for case-sensitivity. 025 * Windows is case-insensitive, Unix is case-sensitive. 026 * <p> 027 * This class captures that difference, providing an enumeration to 028 * control how filename comparisons should be performed. It also provides 029 * methods that use the enumeration to perform comparisons. 030 * <p> 031 * Wherever possible, you should use the <code>check</code> methods in this 032 * class to compare filenames. 033 * 034 * @version $Id: IOCase.java 1483915 2013-05-17 17:02:35Z sebb $ 035 * @since 1.3 036 */ 037public enum IOCase implements Serializable { 038 039 /** 040 * The constant for case sensitive regardless of operating system. 041 */ 042 SENSITIVE ("Sensitive", true), 043 044 /** 045 * The constant for case insensitive regardless of operating system. 046 */ 047 INSENSITIVE ("Insensitive", false), 048 049 /** 050 * The constant for case sensitivity determined by the current operating system. 051 * Windows is case-insensitive when comparing filenames, Unix is case-sensitive. 052 * <p> 053 * <strong>Note:</strong> This only caters for Windows and Unix. Other operating 054 * systems (e.g. OSX and OpenVMS) are treated as case sensitive if they use the 055 * Unix file separator and case-insensitive if they use the Windows file separator 056 * (see {@link java.io.File#separatorChar}). 057 * <p> 058 * If you derialize this constant of Windows, and deserialize on Unix, or vice 059 * versa, then the value of the case-sensitivity flag will change. 060 */ 061 SYSTEM ("System", !FilenameUtils.isSystemWindows()); 062 063 /** Serialization version. */ 064 private static final long serialVersionUID = -6343169151696340687L; 065 066 /** The enumeration name. */ 067 private final String name; 068 069 /** The sensitivity flag. */ 070 private final transient boolean sensitive; 071 072 //----------------------------------------------------------------------- 073 /** 074 * Factory method to create an IOCase from a name. 075 * 076 * @param name the name to find 077 * @return the IOCase object 078 * @throws IllegalArgumentException if the name is invalid 079 */ 080 public static IOCase forName(final String name) { 081 for (IOCase ioCase : IOCase.values()) 082 { 083 if (ioCase.getName().equals(name)) 084 { 085 return ioCase; 086 } 087 } 088 throw new IllegalArgumentException("Invalid IOCase name: " + name); 089 } 090 091 //----------------------------------------------------------------------- 092 /** 093 * Private constructor. 094 * 095 * @param name the name 096 * @param sensitive the sensitivity 097 */ 098 private IOCase(final String name, final boolean sensitive) { 099 this.name = name; 100 this.sensitive = sensitive; 101 } 102 103 /** 104 * Replaces the enumeration from the stream with a real one. 105 * This ensures that the correct flag is set for SYSTEM. 106 * 107 * @return the resolved object 108 */ 109 private Object readResolve() { 110 return forName(name); 111 } 112 113 //----------------------------------------------------------------------- 114 /** 115 * Gets the name of the constant. 116 * 117 * @return the name of the constant 118 */ 119 public String getName() { 120 return name; 121 } 122 123 /** 124 * Does the object represent case sensitive comparison. 125 * 126 * @return true if case sensitive 127 */ 128 public boolean isCaseSensitive() { 129 return sensitive; 130 } 131 132 //----------------------------------------------------------------------- 133 /** 134 * Compares two strings using the case-sensitivity rule. 135 * <p> 136 * This method mimics {@link String#compareTo} but takes case-sensitivity 137 * into account. 138 * 139 * @param str1 the first string to compare, not null 140 * @param str2 the second string to compare, not null 141 * @return true if equal using the case rules 142 * @throws NullPointerException if either string is null 143 */ 144 public int checkCompareTo(final String str1, final String str2) { 145 if (str1 == null || str2 == null) { 146 throw new NullPointerException("The strings must not be null"); 147 } 148 return sensitive ? str1.compareTo(str2) : str1.compareToIgnoreCase(str2); 149 } 150 151 /** 152 * Compares two strings using the case-sensitivity rule. 153 * <p> 154 * This method mimics {@link String#equals} but takes case-sensitivity 155 * into account. 156 * 157 * @param str1 the first string to compare, not null 158 * @param str2 the second string to compare, not null 159 * @return true if equal using the case rules 160 * @throws NullPointerException if either string is null 161 */ 162 public boolean checkEquals(final String str1, final String str2) { 163 if (str1 == null || str2 == null) { 164 throw new NullPointerException("The strings must not be null"); 165 } 166 return sensitive ? str1.equals(str2) : str1.equalsIgnoreCase(str2); 167 } 168 169 /** 170 * Checks if one string starts with another using the case-sensitivity rule. 171 * <p> 172 * This method mimics {@link String#startsWith(String)} but takes case-sensitivity 173 * into account. 174 * 175 * @param str the string to check, not null 176 * @param start the start to compare against, not null 177 * @return true if equal using the case rules 178 * @throws NullPointerException if either string is null 179 */ 180 public boolean checkStartsWith(final String str, final String start) { 181 return str.regionMatches(!sensitive, 0, start, 0, start.length()); 182 } 183 184 /** 185 * Checks if one string ends with another using the case-sensitivity rule. 186 * <p> 187 * This method mimics {@link String#endsWith} but takes case-sensitivity 188 * into account. 189 * 190 * @param str the string to check, not null 191 * @param end the end to compare against, not null 192 * @return true if equal using the case rules 193 * @throws NullPointerException if either string is null 194 */ 195 public boolean checkEndsWith(final String str, final String end) { 196 final int endLen = end.length(); 197 return str.regionMatches(!sensitive, str.length() - endLen, end, 0, endLen); 198 } 199 200 /** 201 * Checks if one string contains another starting at a specific index using the 202 * case-sensitivity rule. 203 * <p> 204 * This method mimics parts of {@link String#indexOf(String, int)} 205 * but takes case-sensitivity into account. 206 * 207 * @param str the string to check, not null 208 * @param strStartIndex the index to start at in str 209 * @param search the start to search for, not null 210 * @return the first index of the search String, 211 * -1 if no match or {@code null} string input 212 * @throws NullPointerException if either string is null 213 * @since 2.0 214 */ 215 public int checkIndexOf(final String str, final int strStartIndex, final String search) { 216 final int endIndex = str.length() - search.length(); 217 if (endIndex >= strStartIndex) { 218 for (int i = strStartIndex; i <= endIndex; i++) { 219 if (checkRegionMatches(str, i, search)) { 220 return i; 221 } 222 } 223 } 224 return -1; 225 } 226 227 /** 228 * Checks if one string contains another at a specific index using the case-sensitivity rule. 229 * <p> 230 * This method mimics parts of {@link String#regionMatches(boolean, int, String, int, int)} 231 * but takes case-sensitivity into account. 232 * 233 * @param str the string to check, not null 234 * @param strStartIndex the index to start at in str 235 * @param search the start to search for, not null 236 * @return true if equal using the case rules 237 * @throws NullPointerException if either string is null 238 */ 239 public boolean checkRegionMatches(final String str, final int strStartIndex, final String search) { 240 return str.regionMatches(!sensitive, strStartIndex, search, 0, search.length()); 241 } 242 243 //----------------------------------------------------------------------- 244 /** 245 * Gets a string describing the sensitivity. 246 * 247 * @return a string describing the sensitivity 248 */ 249 @Override 250 public String toString() { 251 return name; 252 } 253 254}