001/* 002 * Copyright (C) 2006 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.base; 018 019import static com.google.common.base.Preconditions.checkNotNull; 020 021import com.google.common.annotations.GwtCompatible; 022 023/** 024 * Utility class for converting between various ASCII case formats. 025 * 026 * @author Mike Bostock 027 * @since 1.0 028 */ 029@GwtCompatible 030public enum CaseFormat { 031 /** 032 * Hyphenated variable naming convention, e.g., "lower-hyphen". 033 */ 034 LOWER_HYPHEN(CharMatcher.is('-'), "-") { 035 @Override String normalizeWord(String word) { 036 return Ascii.toLowerCase(word); 037 } 038 @Override String convert(CaseFormat format, String s) { 039 if (format == LOWER_UNDERSCORE) { 040 return s.replace('-', '_'); 041 } 042 if (format == UPPER_UNDERSCORE) { 043 return Ascii.toUpperCase(s.replace('-', '_')); 044 } 045 return super.convert(format, s); 046 } 047 }, 048 049 /** 050 * C++ variable naming convention, e.g., "lower_underscore". 051 */ 052 LOWER_UNDERSCORE(CharMatcher.is('_'), "_") { 053 @Override String normalizeWord(String word) { 054 return Ascii.toLowerCase(word); 055 } 056 @Override String convert(CaseFormat format, String s) { 057 if (format == LOWER_HYPHEN) { 058 return s.replace('_', '-'); 059 } 060 if (format == UPPER_UNDERSCORE) { 061 return Ascii.toUpperCase(s); 062 } 063 return super.convert(format, s); 064 } 065 }, 066 067 /** 068 * Java variable naming convention, e.g., "lowerCamel". 069 */ 070 LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), "") { 071 @Override String normalizeWord(String word) { 072 return firstCharOnlyToUpper(word); 073 } 074 }, 075 076 /** 077 * Java and C++ class naming convention, e.g., "UpperCamel". 078 */ 079 UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), "") { 080 @Override String normalizeWord(String word) { 081 return firstCharOnlyToUpper(word); 082 } 083 }, 084 085 /** 086 * Java and C++ constant naming convention, e.g., "UPPER_UNDERSCORE". 087 */ 088 UPPER_UNDERSCORE(CharMatcher.is('_'), "_") { 089 @Override String normalizeWord(String word) { 090 return Ascii.toUpperCase(word); 091 } 092 @Override String convert(CaseFormat format, String s) { 093 if (format == LOWER_HYPHEN) { 094 return Ascii.toLowerCase(s.replace('_', '-')); 095 } 096 if (format == LOWER_UNDERSCORE) { 097 return Ascii.toLowerCase(s); 098 } 099 return super.convert(format, s); 100 } 101 }; 102 103 private final CharMatcher wordBoundary; 104 private final String wordSeparator; 105 106 CaseFormat(CharMatcher wordBoundary, String wordSeparator) { 107 this.wordBoundary = wordBoundary; 108 this.wordSeparator = wordSeparator; 109 } 110 111 /** 112 * Converts the specified {@code String str} from this format to the specified {@code format}. A 113 * "best effort" approach is taken; if {@code str} does not conform to the assumed format, then 114 * the behavior of this method is undefined but we make a reasonable effort at converting anyway. 115 */ 116 public final String to(CaseFormat format, String str) { 117 checkNotNull(format); 118 checkNotNull(str); 119 return (format == this) ? str : convert(format, str); 120 } 121 122 /** 123 * Enum values can override for performance reasons. 124 */ 125 String convert(CaseFormat format, String s) { 126 // deal with camel conversion 127 StringBuilder out = null; 128 int i = 0; 129 int j = -1; 130 while ((j = wordBoundary.indexIn(s, ++j)) != -1) { 131 if (i == 0) { 132 // include some extra space for separators 133 out = new StringBuilder(s.length() + 4 * wordSeparator.length()); 134 out.append(format.normalizeFirstWord(s.substring(i, j))); 135 } else { 136 out.append(format.normalizeWord(s.substring(i, j))); 137 } 138 out.append(format.wordSeparator); 139 i = j + wordSeparator.length(); 140 } 141 return (i == 0) 142 ? format.normalizeFirstWord(s) 143 : out.append(format.normalizeWord(s.substring(i))).toString(); 144 } 145 146 abstract String normalizeWord(String word); 147 148 private String normalizeFirstWord(String word) { 149 return (this == LOWER_CAMEL) ? Ascii.toLowerCase(word) : normalizeWord(word); 150 } 151 152 private static String firstCharOnlyToUpper(String word) { 153 return (word.isEmpty()) 154 ? word 155 : new StringBuilder(word.length()) 156 .append(Ascii.toUpperCase(word.charAt(0))) 157 .append(Ascii.toLowerCase(word.substring(1))) 158 .toString(); 159 } 160}