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.io;
18 
19 import java.io.Serializable;
20 
21 /**
22  * Enumeration of IO case sensitivity.
23  * <p>
24  * Different filing systems have different rules for case-sensitivity.
25  * Windows is case-insensitive, Unix is case-sensitive.
26  * <p>
27  * This class captures that difference, providing an enumeration to
28  * control how filename comparisons should be performed. It also provides
29  * methods that use the enumeration to perform comparisons.
30  * <p>
31  * Wherever possible, you should use the <code>check</code> methods in this
32  * class to compare filenames.
33  *
34  * @author Stephen Colebourne
35  * @version $Id: IOCase.java 606345 2007-12-21 23:43:01Z ggregory $
36  * @since Commons IO 1.3
37  */
38 public final class IOCase implements Serializable {
39 
40     /**
41      * The constant for case sensitive regardless of operating system.
42      */
43     public static final IOCase SENSITIVE = new IOCase("Sensitive", true);
44 
45     /**
46      * The constant for case insensitive regardless of operating system.
47      */
48     public static final IOCase INSENSITIVE = new IOCase("Insensitive", false);
49 
50     /**
51      * The constant for case sensitivity determined by the current operating system.
52      * Windows is case-insensitive when comparing filenames, Unix is case-sensitive.
53      * <p>
54      * If you derialize this constant of Windows, and deserialize on Unix, or vice
55      * versa, then the value of the case-sensitivity flag will change.
56      */
57     public static final IOCase SYSTEM = new IOCase("System", !FilenameUtils.isSystemWindows());
58 
59     /** Serialization version. */
60     private static final long serialVersionUID = -6343169151696340687L;
61 
62     /** The enumeration name. */
63     private final String name;
64 
65     /** The sensitivity flag. */
66     private final transient boolean sensitive;
67 
68     //-----------------------------------------------------------------------
69     /**
70      * Factory method to create an IOCase from a name.
71      *
72      * @param name  the name to find
73      * @return the IOCase object
74      * @throws IllegalArgumentException if the name is invalid
75      */
forName(String name)76     public static IOCase forName(String name) {
77         if (IOCase.SENSITIVE.name.equals(name)){
78             return IOCase.SENSITIVE;
79         }
80         if (IOCase.INSENSITIVE.name.equals(name)){
81             return IOCase.INSENSITIVE;
82         }
83         if (IOCase.SYSTEM.name.equals(name)){
84             return IOCase.SYSTEM;
85         }
86         throw new IllegalArgumentException("Invalid IOCase name: " + name);
87     }
88 
89     //-----------------------------------------------------------------------
90     /**
91      * Private constructor.
92      *
93      * @param name  the name
94      * @param sensitive  the sensitivity
95      */
IOCase(String name, boolean sensitive)96     private IOCase(String name, boolean sensitive) {
97         this.name = name;
98         this.sensitive = sensitive;
99     }
100 
101     /**
102      * Replaces the enumeration from the stream with a real one.
103      * This ensures that the correct flag is set for SYSTEM.
104      *
105      * @return the resolved object
106      */
readResolve()107     private Object readResolve() {
108         return forName(name);
109     }
110 
111     //-----------------------------------------------------------------------
112     /**
113      * Gets the name of the constant.
114      *
115      * @return the name of the constant
116      */
getName()117     public String getName() {
118         return name;
119     }
120 
121     /**
122      * Does the object represent case sensitive comparison.
123      *
124      * @return true if case sensitive
125      */
isCaseSensitive()126     public boolean isCaseSensitive() {
127         return sensitive;
128     }
129 
130     //-----------------------------------------------------------------------
131     /**
132      * Compares two strings using the case-sensitivity rule.
133      * <p>
134      * This method mimics {@link String#compareTo} but takes case-sensitivity
135      * into account.
136      *
137      * @param str1  the first string to compare, not null
138      * @param str2  the second string to compare, not null
139      * @return true if equal using the case rules
140      * @throws NullPointerException if either string is null
141      */
checkCompareTo(String str1, String str2)142     public int checkCompareTo(String str1, String str2) {
143         if (str1 == null || str2 == null) {
144             throw new NullPointerException("The strings must not be null");
145         }
146         return sensitive ? str1.compareTo(str2) : str1.compareToIgnoreCase(str2);
147     }
148 
149     /**
150      * Compares two strings using the case-sensitivity rule.
151      * <p>
152      * This method mimics {@link String#equals} but takes case-sensitivity
153      * into account.
154      *
155      * @param str1  the first string to compare, not null
156      * @param str2  the second string to compare, not null
157      * @return true if equal using the case rules
158      * @throws NullPointerException if either string is null
159      */
checkEquals(String str1, String str2)160     public boolean checkEquals(String str1, String str2) {
161         if (str1 == null || str2 == null) {
162             throw new NullPointerException("The strings must not be null");
163         }
164         return sensitive ? str1.equals(str2) : str1.equalsIgnoreCase(str2);
165     }
166 
167     /**
168      * Checks if one string starts with another using the case-sensitivity rule.
169      * <p>
170      * This method mimics {@link String#startsWith(String)} but takes case-sensitivity
171      * into account.
172      *
173      * @param str  the string to check, not null
174      * @param start  the start to compare against, not null
175      * @return true if equal using the case rules
176      * @throws NullPointerException if either string is null
177      */
checkStartsWith(String str, String start)178     public boolean checkStartsWith(String str, String start) {
179         return str.regionMatches(!sensitive, 0, start, 0, start.length());
180     }
181 
182     /**
183      * Checks if one string ends with another using the case-sensitivity rule.
184      * <p>
185      * This method mimics {@link String#endsWith} but takes case-sensitivity
186      * into account.
187      *
188      * @param str  the string to check, not null
189      * @param end  the end to compare against, not null
190      * @return true if equal using the case rules
191      * @throws NullPointerException if either string is null
192      */
checkEndsWith(String str, String end)193     public boolean checkEndsWith(String str, String end) {
194         int endLen = end.length();
195         return str.regionMatches(!sensitive, str.length() - endLen, end, 0, endLen);
196     }
197 
198     /**
199      * Checks if one string contains another at a specific index using the case-sensitivity rule.
200      * <p>
201      * This method mimics parts of {@link String#regionMatches(boolean, int, String, int, int)}
202      * but takes case-sensitivity into account.
203      *
204      * @param str  the string to check, not null
205      * @param strStartIndex  the index to start at in str
206      * @param search  the start to search for, not null
207      * @return true if equal using the case rules
208      * @throws NullPointerException if either string is null
209      */
checkRegionMatches(String str, int strStartIndex, String search)210     public boolean checkRegionMatches(String str, int strStartIndex, String search) {
211         return str.regionMatches(!sensitive, strStartIndex, search, 0, search.length());
212     }
213 
214     /**
215      * Converts the case of the input String to a standard format.
216      * Subsequent operations can then use standard String methods.
217      *
218      * @param str  the string to convert, null returns null
219      * @return the lower-case version if case-insensitive
220      */
convertCase(String str)221     String convertCase(String str) {
222         if (str == null) {
223             return null;
224         }
225         return sensitive ? str : str.toLowerCase();
226     }
227 
228     //-----------------------------------------------------------------------
229     /**
230      * Gets a string describing the sensitivity.
231      *
232      * @return a string describing the sensitivity
233      */
toString()234     public String toString() {
235         return name;
236     }
237 
238 }
239