View Javadoc
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</code> 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 }