| /* |
| * Copyright 2013 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.jimfs; |
| |
| import com.google.common.base.Ascii; |
| import com.google.common.base.Function; |
| |
| import com.ibm.icu.lang.UCharacter; |
| |
| import java.text.Normalizer; |
| import java.util.regex.Pattern; |
| |
| /** |
| * Normalizations that can be applied to names in paths. Includes Unicode normalizations and |
| * normalizations for case insensitive paths. These normalizations can be set in |
| * {@code Configuration.Builder} when creating a Jimfs file system instance and are automatically |
| * applied to paths in the file system. |
| * |
| * @author Colin Decker |
| */ |
| public enum PathNormalization implements Function<String, String> { |
| |
| /** |
| * No normalization. |
| */ |
| NONE(0) { |
| @Override |
| public String apply(String string) { |
| return string; |
| } |
| }, |
| |
| /** |
| * Unicode composed normalization (form {@linkplain java.text.Normalizer.Form#NFC NFC}). |
| */ |
| NFC(Pattern.CANON_EQ) { |
| @Override |
| public String apply(String string) { |
| return Normalizer.normalize(string, Normalizer.Form.NFC); |
| } |
| }, |
| |
| /** |
| * Unicode decomposed normalization (form {@linkplain java.text.Normalizer.Form#NFD NFD}). |
| */ |
| NFD(Pattern.CANON_EQ) { |
| @Override |
| public String apply(String string) { |
| return Normalizer.normalize(string, Normalizer.Form.NFD); |
| } |
| }, |
| |
| /** |
| * Unicode case folding for case insensitive paths. Requires ICU4J on the classpath. |
| */ |
| CASE_FOLD_UNICODE(Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) { |
| // TODO(cgdecker): This does default case folding, e.g. non-Turkish case folding. |
| // Should there be an option to use the Turkish-correct case folding instead? |
| @Override |
| public String apply(String string) { |
| try { |
| return UCharacter.foldCase(string, true); |
| } catch (NoClassDefFoundError e) { |
| NoClassDefFoundError error = |
| new NoClassDefFoundError( |
| "PathNormalization.CASE_FOLD_UNICODE requires ICU4J. " |
| + "Did you forget to include it on your classpath?"); |
| error.initCause(e); |
| throw error; |
| } |
| } |
| }, |
| |
| /** |
| * ASCII case folding for simple case insensitive paths. |
| */ |
| CASE_FOLD_ASCII(Pattern.CASE_INSENSITIVE) { |
| @Override |
| public String apply(String string) { |
| return Ascii.toLowerCase(string); |
| } |
| }; |
| |
| private final int patternFlags; |
| |
| private PathNormalization(int patternFlags) { |
| this.patternFlags = patternFlags; |
| } |
| |
| /** |
| * Applies this normalization to the given string, returning the normalized result. |
| */ |
| @Override |
| public abstract String apply(String string); |
| |
| /** |
| * Returns the flags that should be used when creating a regex {@link Pattern} in order to |
| * approximate this normalization. |
| */ |
| public int patternFlags() { |
| return patternFlags; |
| } |
| |
| /** |
| * Applies the given normalizations to the given string in order, returning the normalized |
| * result. |
| */ |
| public static String normalize(String string, Iterable<PathNormalization> normalizations) { |
| String result = string; |
| for (PathNormalization normalization : normalizations) { |
| result = normalization.apply(result); |
| } |
| return result; |
| } |
| |
| /** |
| * Compiles a regex pattern using flags based on the given normalizations. |
| */ |
| public static Pattern compilePattern(String regex, Iterable<PathNormalization> normalizations) { |
| int flags = 0; |
| for (PathNormalization normalization : normalizations) { |
| flags |= normalization.patternFlags(); |
| } |
| return Pattern.compile(regex, flags); |
| } |
| } |