001package com.avaje.ebean.config; 002 003import com.avaje.ebean.util.CamelCaseHelper; 004 005/** 006 * Converts between Camel Case and Underscore based names for both table and 007 * column names (and is the default naming convention in Ebean). 008 * 009 * @author emcgreal 010 * @author rbygrave 011 */ 012public class UnderscoreNamingConvention extends AbstractNamingConvention { 013 014 /** 015 * Force toUnderscore to return in upper case. 016 */ 017 private boolean forceUpperCase = false; 018 019 /** 020 * The digits compressed. 021 */ 022 private boolean digitsCompressed = true; 023 024 /** 025 * Create with a given sequence format. 026 * 027 * @param sequenceFormat the sequence format 028 */ 029 public UnderscoreNamingConvention(String sequenceFormat) { 030 super(sequenceFormat); 031 } 032 033 /** 034 * Create with a sequence format of "{table}_seq". 035 */ 036 public UnderscoreNamingConvention() { 037 super(); 038 } 039 040 /** 041 * Returns the last part of the class name. 042 * 043 * @param beanClass the bean class 044 * @return the table name from class 045 */ 046 public TableName getTableNameByConvention(Class<?> beanClass) { 047 048 return new TableName(getCatalog(), getSchema(), toUnderscoreFromCamel(beanClass.getSimpleName())); 049 } 050 051 /** 052 * Converts Camel case property name to underscore based column name. 053 * 054 * @return the column from property 055 */ 056 public String getColumnFromProperty(Class<?> beanClass, String propertyName) { 057 058 return toUnderscoreFromCamel(propertyName); 059 } 060 061 /** 062 * Converts underscore based column name to Camel case property name. 063 * 064 * @param beanClass the bean class 065 * @param dbColumnName the db column name 066 * @return the property from column 067 */ 068 public String getPropertyFromColumn(Class<?> beanClass, String dbColumnName) { 069 return toCamelFromUnderscore(dbColumnName); 070 } 071 072 /** 073 * Return true if the result will be upper case. 074 * <p> 075 * False if it will be lower case. 076 * </p> 077 */ 078 public boolean isForceUpperCase() { 079 return forceUpperCase; 080 } 081 082 /** 083 * Set to true to make the result upper case. 084 */ 085 public void setForceUpperCase(boolean forceUpperCase) { 086 this.forceUpperCase = forceUpperCase; 087 } 088 089 /** 090 * Returns true if digits are compressed. 091 */ 092 public boolean isDigitsCompressed() { 093 return digitsCompressed; 094 } 095 096 /** 097 * Sets to true for digits to be compressed (without a leading underscore). 098 */ 099 public void setDigitsCompressed(boolean digitsCompressed) { 100 this.digitsCompressed = digitsCompressed; 101 } 102 103 /** 104 * Convert and return the string to underscore from camel case. 105 */ 106 protected String toUnderscoreFromCamel(String camelCase) { 107 108 int lastUpper = -1; 109 StringBuilder sb = new StringBuilder(camelCase.length()+4); 110 for (int i = 0; i < camelCase.length(); i++) { 111 char c = camelCase.charAt(i); 112 113 if ('_' == c) { 114 // Underscores should just be passed through 115 sb.append(c); 116 lastUpper = i; 117 } else if (Character.isDigit(c)) { 118 if (i > lastUpper + 1 && !digitsCompressed) { 119 sb.append("_"); 120 } 121 sb.append(c); 122 lastUpper = i; 123 124 } else if (Character.isUpperCase(c)) { 125 if (i > lastUpper + 1) { 126 sb.append("_"); 127 } 128 sb.append(Character.toLowerCase(c)); 129 lastUpper = i; 130 131 } else { 132 sb.append(c); 133 } 134 } 135 String ret = sb.toString(); 136 if (forceUpperCase) { 137 ret = ret.toUpperCase(); 138 } 139 return ret; 140 } 141 142 /** 143 * Convert and return the from string from underscore to camel case. 144 */ 145 protected String toCamelFromUnderscore(String underscore) { 146 return CamelCaseHelper.toCamelFromUnderscore(underscore); 147 } 148}