• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.base;
18 
19 import java.util.Locale;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22 
23 /**
24  * Utility class for converting between various case formats.
25  *
26  * @author Mike Bostock
27  * @since 2009.09.15 <b>tentative</b>
28  */
29 public enum CaseFormat {
30 
31   /**
32    * Hyphenated variable naming convention, e.g., "lower-hyphen".
33    */
34   LOWER_HYPHEN(Pattern.compile("[-]"), "-"),
35 
36   /**
37    * C++ variable naming convention, e.g., "lower_underscore".
38    */
39   LOWER_UNDERSCORE(Pattern.compile("[_]"), "_"),
40 
41   /**
42    * Java variable naming convention, e.g., "lowerCamel".
43    */
44   LOWER_CAMEL(Pattern.compile("[A-Z]"), ""),
45 
46   /**
47    * Java and C++ class naming convention, e.g., "UpperCamel".
48    */
49   UPPER_CAMEL(Pattern.compile("[A-Z]"), ""),
50 
51   /**
52    * Java and C++ constant naming convention, e.g., "UPPER_UNDERSCORE".
53    */
54   UPPER_UNDERSCORE(Pattern.compile("[_]"), "_");
55 
56   private final Pattern wordBoundary;
57   private final String wordSeparator;
58 
CaseFormat(Pattern wordBoundary, String wordSeparator)59   private CaseFormat(Pattern wordBoundary, String wordSeparator) {
60     this.wordBoundary = wordBoundary;
61     this.wordSeparator = wordSeparator;
62   }
63 
64   /**
65    * Converts the specified {@code String s} from this format to the specified
66    * {@code format}. A "best effort" approach is taken; if {@code s} does not
67    * conform to the assumed format, then the behavior of this method is
68    * undefined but we make a reasonable effort at converting anyway.
69    */
to(CaseFormat format, String s)70   public String to(CaseFormat format, String s) {
71     if (format == null) {
72       throw new NullPointerException();
73     }
74     if (s == null) {
75       throw new NullPointerException();
76     }
77 
78     /* optimize case where no conversion is required */
79     if (format == this) {
80       return s;
81     }
82 
83     /* optimize cases where no camel conversion is required */
84     switch (this) {
85       case LOWER_HYPHEN:
86         switch (format) {
87           case LOWER_UNDERSCORE: return s.replace("-", "_");
88           case UPPER_UNDERSCORE: return s.replace("-", "_").toUpperCase(Locale.US);
89         }
90         break;
91       case LOWER_UNDERSCORE:
92         switch (format) {
93           case LOWER_HYPHEN: return s.replace("_", "-");
94           case UPPER_UNDERSCORE: return s.toUpperCase(Locale.US);
95         }
96         break;
97       case UPPER_UNDERSCORE:
98         switch (format) {
99           case LOWER_HYPHEN: return s.replace("_", "-").toLowerCase(Locale.US);
100           case LOWER_UNDERSCORE: return s.toLowerCase(Locale.US);
101         }
102         break;
103     }
104 
105     /* otherwise, deal with camel conversion */
106     StringBuilder out = null;
107     int i = 0;
108     for (Matcher matcher = wordBoundary.matcher(s); matcher.find();) {
109       int j = matcher.start();
110       if (i == 0) {
111         /* include some extra space for separators */
112         out = new StringBuilder(s.length() + 4 * wordSeparator.length());
113         out.append(format.normalizeFirstWord(s.substring(i, j)));
114       } else {
115         out.append(format.normalizeWord(s.substring(i, j)));
116       }
117       out.append(format.wordSeparator);
118       i = j + wordSeparator.length();
119     }
120     if (i == 0) {
121       return format.normalizeFirstWord(s);
122     }
123     out.append(format.normalizeWord(s.substring(i)));
124     return out.toString();
125   }
126 
normalizeFirstWord(String word)127   private String normalizeFirstWord(String word) {
128     switch (this) {
129       case LOWER_CAMEL: return word.toLowerCase(Locale.US);
130       default: return normalizeWord(word);
131     }
132   }
133 
normalizeWord(String word)134   private String normalizeWord(String word) {
135     switch (this) {
136       case LOWER_HYPHEN: return word.toLowerCase(Locale.US);
137       case LOWER_UNDERSCORE: return word.toLowerCase(Locale.US);
138       case LOWER_CAMEL: return toTitleCase(word);
139       case UPPER_CAMEL: return toTitleCase(word);
140       case UPPER_UNDERSCORE: return word.toUpperCase(Locale.US);
141     }
142     throw new RuntimeException("unknown case: " + this);
143   }
144 
toTitleCase(String word)145   private static String toTitleCase(String word) {
146     return (word.length() < 2) ? word.toUpperCase(Locale.US)
147         : (Character.toTitleCase(word.charAt(0))
148            + word.substring(1).toLowerCase(Locale.US));
149   }
150 
151 }
152