`GriffonNameUtils.java`
`001 /* 002 * Copyright 2008-2012 the original author or 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 package griffon.util; 017 018 import java.util.ArrayList; 019 import java.util.Iterator; 020 import java.util.List; 021 import java.util.Locale; 022 023 /** 024 * Contains utility methods for converting between different name types, 025 * for example from class names -&gt; property names and vice-versa. The 026 * key aspect of this class is that it has no dependencies outside the 027 * JDK! 028 */ 029 public class GriffonNameUtils { 030 private static final String PROPERTY_SET_PREFIX = "set"; 031 032 /** 033 * Capitalizes a String (makes the first char uppercase) taking care 034 * of blank strings and single character strings. 035 * 036 * @param str The String to be capitalized 037 * @return Capitalized version of the target string if it is not blank 038 */ 039 public static String capitalize(String str) { 040 if (isBlank(str)) return str; 041 if (str.length() == 1) return str.toUpperCase(); 042 return str.substring(0, 1).toUpperCase(Locale.ENGLISH) + str.substring(1); 043 } 044 045 /** 046 * Uncapitalizes a String (makes the first char lowercase) taking care 047 * of blank strings and single character strings. 048 * 049 * @param str The String to be uncapitalized 050 * @return Uncapitalized version of the target string if it is not blank 051 */ 052 public static String uncapitalize(String str) { 053 if (isBlank(str)) return str; 054 if (str.length() == 1) return String.valueOf(Character.toLowerCase(str.charAt(0))); 055 return Character.toLowerCase(str.charAt(0)) + str.substring(1); 056 } 057 058 /** 059 * Retrieves the name of a setter for the specified property name 060 * 061 * @param propertyName The property name 062 * @return The setter equivalent 063 */ 064 public static String getSetterName(String propertyName) { 065 return PROPERTY_SET_PREFIX + capitalize(propertyName); 066 } 067 068 /** 069 * Calculate the name for a getter method to retrieve the specified property 070 * 071 * @param propertyName 072 * @return The name for the getter method for this property, if it were to exist, i.e. getConstraints 073 */ 074 public static String getGetterName(String propertyName) { 075 return "get" + capitalize(propertyName); 076 } 077 078 /** 079 * Returns the class name for the given logical name and trailing name. For example "person" and "Controller" would evaluate to "PersonController" 080 * 081 * @param logicalName The logical name 082 * @param trailingName The trailing name 083 * @return The class name 084 */ 085 public static String getClassName(String logicalName, String trailingName) { 086 if (isBlank(logicalName)) { 087 throw new IllegalArgumentException("Argument [logicalName] cannot be null or blank"); 088 } 089 090 String className = capitalize(logicalName); 091 if (trailingName != null) { 092 className = className + trailingName; 093 } 094 return className; 095 } 096 097 /** 098 * Returns the class name representation of the given name 099 * 100 * @param name The name to convert 101 * @return The property name representation 102 */ 103 public static String getClassNameRepresentation(String name) { 104 StringBuilder buf = new StringBuilder(); 105 if (name != null && name.length() > 0) { 106 String[] tokens = name.split("[^\\w\\d]"); 107 for (String token1 : tokens) { 108 String token = token1.trim(); 109 buf.append(capitalize(token)); 110 } 111 } 112 113 return buf.toString(); 114 } 115 116 /** 117 * Converts foo-bar into FooBar. Empty and null strings are returned 118 * as-is. 119 * 120 * @param name The lower case hyphen separated name 121 * @return The class name equivalent. 122 */ 123 public static String getClassNameForLowerCaseHyphenSeparatedName(String name) { 124 // Handle null and empty strings. 125 if (isBlank(name)) return name; 126 127 if (name.indexOf('-') > -1) { 128 StringBuilder buf = new StringBuilder(); 129 String[] tokens = name.split("-"); 130 for (String token : tokens) { 131 if (token == null || token.length() == 0) continue; 132 buf.append(capitalize(token)); 133 } 134 return buf.toString(); 135 } 136 137 return capitalize(name); 138 } 139 140 /** 141 * Retrieves the logical class name of a Griffon artifact given the Griffon class 142 * and a specified trailing name 143 * 144 * @param clazz The class 145 * @param trailingName The trailing name such as "Controller" or "TagLib" 146 * @return The logical class name 147 */ 148 public static String getLogicalName(Class<?> clazz, String trailingName) { 149 return getLogicalName(clazz.getName(), trailingName); 150 } 151 152 /** 153 * Retrieves the logical name of the class without the trailing name 154 * 155 * @param name The name of the class 156 * @param trailingName The trailing name 157 * @return The logical name 158 */ 159 public static String getLogicalName(String name, String trailingName) { 160 if (!isBlank(trailingName)) { 161 String shortName = getShortName(name); 162 if (shortName.indexOf(trailingName) > -1) { 163 return shortName.substring(0, shortName.length() - trailingName.length()); 164 } 165 } 166 return name; 167 } 168 169 public static String getLogicalPropertyName(String className, String trailingName) { 170 if (!isBlank(className) && !isBlank(trailingName)) { 171 if (className.length() == trailingName.length() + 1 && className.endsWith(trailingName)) { 172 return className.substring(0, 1).toLowerCase(); 173 } 174 } 175 return getLogicalName(getPropertyName(className), trailingName); 176 } 177 178 /** 179 * Shorter version of getPropertyNameRepresentation 180 * 181 * @param name The name to convert 182 * @return The property name version 183 */ 184 public static String getPropertyName(String name) { 185 return getPropertyNameRepresentation(name); 186 } 187 188 /** 189 * Shorter version of getPropertyNameRepresentation 190 * 191 * @param clazz The clazz to convert 192 * @return The property name version 193 */ 194 public static String getPropertyName(Class<?> clazz) { 195 return getPropertyNameRepresentation(clazz); 196 } 197 198 /** 199 * Returns the property name equivalent for the specified class 200 * 201 * @param targetClass The class to get the property name for 202 * @return A property name reperesentation of the class name (eg. MyClass becomes myClass) 203 */ 204 public static String getPropertyNameRepresentation(Class<?> targetClass) { 205 String shortName = getShortName(targetClass); 206 return getPropertyNameRepresentation(shortName); 207 } 208 209 /** 210 * Returns the property name representation of the given name 211 * 212 * @param name The name to convert 213 * @return The property name representation 214 */ 215 public static String getPropertyNameRepresentation(String name) { 216 // Strip any package from the name. 217 int pos = name.lastIndexOf('.'); 218 if (pos != -1) { 219 name = name.substring(pos + 1); 220 } 221 222 // Check whether the name begins with two upper case letters. 223 if (name.length() > 1 && Character.isUpperCase(name.charAt(0)) && Character.isUpperCase(name.charAt(1))) { 224 return name; 225 } 226 227 String propertyName = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1); 228 if (propertyName.indexOf(' ') > -1) { 229 propertyName = propertyName.replaceAll("\\s", ""); 230 } 231 return propertyName; 232 } 233 234 /** 235 * Converts foo-bar into fooBar 236 * 237 * @param name The lower case hyphen separated name 238 * @return The property name equivalent 239 */ 240 public static String getPropertyNameForLowerCaseHyphenSeparatedName(String name) { 241 return getPropertyName(getClassNameForLowerCaseHyphenSeparatedName(name)); 242 } 243 244 /** 245 * Returns the class name without the package prefix 246 * 247 * @param targetClass The class to get a short name for 248 * @return The short name of the class 249 */ 250 public static String getShortName(Class<?> targetClass) { 251 String className = targetClass.getName(); 252 return getShortName(className); 253 } 254 255 /** 256 * Returns the class name without the package prefix 257 * 258 * @param className The class name to get a short name for 259 * @return The short name of the class 260 */ 261 public static String getShortName(String className) { 262 int i = className.lastIndexOf("."); 263 if (i > -1) { 264 className = className.substring(i + 1, className.length()); 265 } 266 return className; 267 } 268 269 /** 270 * Converts a property name into its natural language equivalent eg ('firstName' becomes 'First Name') 271 * 272 * @param name The property name to convert 273 * @return The converted property name 274 */ 275 public static String getNaturalName(String name) { 276 name = getShortName(name); 277 List<String> words = new ArrayList<String>(); 278 int i = 0; 279 char[] chars = name.toCharArray(); 280 for (int j = 0; j < chars.length; j++) { 281 char c = chars[j]; 282 String w; 283 if (i >= words.size()) { 284 w = ""; 285 words.add(i, w); 286 } else { 287 w = words.get(i); 288 } 289 290 if (Character.isLowerCase(c) || Character.isDigit(c)) { 291 if (Character.isLowerCase(c) && w.length() == 0) { 292 c = Character.toUpperCase(c); 293 } else if (w.length() > 1 && Character.isUpperCase(w.charAt(w.length() - 1))) { 294 w = ""; 295 words.add(++i, w); 296 } 297 298 words.set(i, w + c); 299 } else if (Character.isUpperCase(c)) { 300 if ((i == 0 && w.length() == 0) || Character.isUpperCase(w.charAt(w.length() - 1))) { 301 words.set(i, w + c); 302 } else { 303 words.add(++i, String.valueOf(c)); 304 } 305 } 306 } 307 308 StringBuilder buf = new StringBuilder(); 309 for (Iterator<String> j = words.iterator(); j.hasNext(); ) { 310 String word = j.next(); 311 buf.append(word); 312 if (j.hasNext()) { 313 buf.append(' '); 314 } 315 } 316 return buf.toString(); 317 } 318 319 /** 320 * <p>Determines whether a given string is <code>null</code>, empty, 321 * or only contains whitespace. If it contains anything other than 322 * whitespace then the string is not considered to be blank and the 323 * method returns <code>false</code>.</p> 324 * <p>We could use Commons Lang for this, but we don't want GriffonNameUtils 325 * to have a dependency on any external library to minimise the number of 326 * dependencies required to bootstrap Griffon.</p> 327 * 328 * @param str The string to test. 329 * @return <code>true</code> if the string is <code>null</code>, or 330 * blank. 331 */ 332 public static boolean isBlank(String str) { 333 return str == null || str.trim().length() == 0; 334 } 335 336 /** 337 * Retrieves the hyphenated name representation of the supplied class. For example 338 * MyFunkyGriffonThingy would be my-funky-griffon-thingy. 339 * 340 * @param clazz The class to convert 341 * @return The hyphenated name representation 342 */ 343 public static String getHyphenatedName(Class clazz) { 344 if (clazz == null) { 345 return null; 346 } 347 return getHyphenatedName(clazz.getName()); 348 } 349 350 /** 351 * Retrieves the hyphenated name representation of the given class name. 352 * For example MyFunkyGriffonThingy would be my-funky-griffon-thingy. 353 * 354 * @param name The class name to convert. 355 * @return The hyphenated name representation. 356 */ 357 public static String getHyphenatedName(String name) { 358 if (name == null) { 359 return null; 360 } 361 if (name.endsWith(".groovy")) { 362 name = name.substring(0, name.length() - 7); 363 } 364 String naturalName = getNaturalName(getShortName(name)); 365 return naturalName.replaceAll("\\s", "-").toLowerCase(); 366 } 367 }`