001: /*
002: * $Id: ModelUtil.java,v 1.5 2004/01/26 17:42:10 ajzeneski Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024: package org.ofbiz.entity.model;
025:
026: import java.io.*;
027:
028: import org.ofbiz.base.util.*;
029:
030: /**
031: * Generic Entity - General Utilities
032: *
033: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
034: * @version $Revision: 1.5 $
035: * @since 2.0
036: */
037: public class ModelUtil {
038:
039: public static final String module = ModelUtil.class.getName();
040:
041: /**
042: * Changes the first letter of the passed String to upper case.
043: * @param string The passed String
044: * @return A String with an upper case first letter
045: */
046: public static String upperFirstChar(String string) {
047: if (string == null)
048: return null;
049: if (string.length() <= 1)
050: return string.toLowerCase();
051: StringBuffer sb = new StringBuffer(string);
052:
053: sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
054: return sb.toString();
055: }
056:
057: /**
058: * Changes the first letter of the passed String to lower case.
059: *
060: * @param string The passed String
061: * @return A String with a lower case first letter
062: */
063: public static String lowerFirstChar(String string) {
064: if (string == null)
065: return null;
066: if (string.length() <= 1)
067: return string.toLowerCase();
068: StringBuffer sb = new StringBuffer(string);
069:
070: sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
071: return sb.toString();
072: }
073:
074: /** Converts a database name to a Java class name.
075: * The naming conventions used to allow for this are as follows: a database name (table or
076: * column) is in all capital letters, and the words are separated by an underscore
077: * (for example: NEAT_ENTITY_NAME or RANDOM_FIELD_NAME); a Java name (ejb or field) is in all
078: * lower case letters, except the letter at the beginning of each word (for example:
079: * NeatEntityName or RandomFieldName). The convention of using a capital letter at
080: * the beginning of a class name in Java, or a lower-case letter for the beginning of a
081: * variable name in Java is also used along with the Java name convention above.
082: * @param columnName The database name
083: * @return The Java class name
084: */
085: public static String dbNameToClassName(String columnName) {
086: return upperFirstChar(dbNameToVarName(columnName));
087: }
088:
089: /** Converts a database name to a Java variable name.
090: * The naming conventions used to allow for this are as follows: a database name (table or
091: * column) is in all capital letters, and the words are separated by an underscore
092: * (for example: NEAT_ENTITY_NAME or RANDOM_FIELD_NAME); a Java name (ejb or field) is in all
093: * lower case letters, except the letter at the beginning of each word (for example:
094: * NeatEntityName or RandomFieldName). The convention of using a capital letter at
095: * the beginning of a class name in Java, or a lower-case letter for the beginning of a
096: * variable name in Java is also used along with the Java name convention above.
097: * @param columnName The database name
098: * @return The Java variable name
099: */
100: public static String dbNameToVarName(String columnName) {
101: if (columnName == null)
102: return null;
103:
104: StringBuffer fieldName = new StringBuffer(columnName.length());
105:
106: boolean toUpper = false;
107: for (int i = 0; i < columnName.length(); i++) {
108: char ch = columnName.charAt(i);
109: if (ch == '_') {
110: toUpper = true;
111: } else if (toUpper) {
112: fieldName.append(Character.toUpperCase(ch));
113: toUpper = false;
114: } else {
115: fieldName.append(Character.toLowerCase(ch));
116: }
117: }
118:
119: return fieldName.toString();
120: }
121:
122: /**
123: * Converts a Java variable name to a database name.
124: * The naming conventions used to allow for this are as follows: a database name (table or
125: * column) is in all capital letters, and the words are separated by an underscore
126: * (for example: NEAT_ENTITY_NAME or RANDOM_FIELD_NAME); a Java name (ejb or field) is in all
127: * lower case letters, except the letter at the beginning of each word (for example:
128: * NeatEntityName or RandomFieldName). The convention of using a capital letter at
129: * the beginning of a class name in Java, or a lower-case letter for the beginning of a
130: * variable name in Java is also used along with the Java name convention above.
131: * @param javaName The Java variable name
132: * @return The database name
133: */
134: public static String javaNameToDbName(String javaName) {
135: if (javaName == null)
136: return null;
137: if (javaName.length() <= 0)
138: return "";
139: StringBuffer dbName = new StringBuffer();
140:
141: dbName.append(Character.toUpperCase(javaName.charAt(0)));
142: int namePos = 1;
143:
144: while (namePos < javaName.length()) {
145: char curChar = javaName.charAt(namePos);
146:
147: if (Character.isUpperCase(curChar))
148: dbName.append('_');
149: dbName.append(Character.toUpperCase(curChar));
150: namePos++;
151: }
152:
153: return dbName.toString();
154: }
155:
156: public static String vowelBag = "aeiouyAEIOUY";
157:
158: /** Start by removing all vowels, then pull 1 letter at a time off the end of each _ separated segment, go until it is less than or equal to the desired length
159: *
160: * @param dbName
161: * @param desiredLength
162: * @return shortened String
163: */
164: public static String shortenDbName(String dbName, int desiredLength) {
165: StringBuffer dbBuf = new StringBuffer(dbName);
166: if (dbBuf.length() > desiredLength) {
167: // remove one vowel at a time, starting at beginning
168: for (int i = dbBuf.length() - 1; i > 0; i--) {
169: // don't remove vowels that are at the beginning of the string (taken care of by the i > 0) or right after an underscore
170: if (dbBuf.charAt(i - 1) == '_') {
171: continue;
172: }
173:
174: char curChar = dbBuf.charAt(i);
175: if (vowelBag.indexOf(curChar) > 0) {
176: dbBuf.deleteCharAt(i);
177: }
178: }
179: }
180:
181: // remove all double underscores
182: while (dbBuf.indexOf("__") > 0) {
183: dbBuf.deleteCharAt(dbBuf.indexOf("__"));
184: }
185:
186: while (dbBuf.length() > desiredLength) {
187: boolean removedChars = false;
188:
189: int usIndex = dbBuf.lastIndexOf("_");
190: while (usIndex > 0 && dbBuf.length() > desiredLength) {
191: // if this is the first word in the group, don't pull letters off unless it is 4 letters or more
192: int prevUsIndex = dbBuf.lastIndexOf("_", usIndex - 1);
193: if (prevUsIndex < 0 && usIndex < 4) {
194: break;
195: }
196:
197: // don't remove characters to reduce the size two less than three characters between underscores
198: if (prevUsIndex >= 0 && (usIndex - prevUsIndex) <= 4) {
199: usIndex = prevUsIndex;
200: continue;
201: }
202:
203: // delete the second to last character instead of the last, better chance of being unique
204: dbBuf.deleteCharAt(usIndex - 2);
205: removedChars = true;
206: if (usIndex > 2) {
207: usIndex = dbBuf.lastIndexOf("_", usIndex - 2);
208: } else {
209: break;
210: }
211: }
212:
213: // now delete the char at the end of the string if necessary
214: if (dbBuf.length() > desiredLength) {
215: int removeIndex = dbBuf.length() - 1;
216: int prevRemoveIndex = dbBuf.lastIndexOf("_",
217: removeIndex - 1);
218: // don't remove characters to reduce the size two less than two characters between underscores
219: if (prevRemoveIndex < 0
220: || (removeIndex - prevRemoveIndex) >= 3) {
221: // delete the second to last character instead of the last, better chance of being unique
222: dbBuf.deleteCharAt(removeIndex - 1);
223: removedChars = true;
224: }
225: }
226:
227: // remove all double underscores
228: while (dbBuf.indexOf("__") > 0) {
229: dbBuf.deleteCharAt(dbBuf.indexOf("__"));
230: removedChars = true;
231: }
232:
233: // if we didn't remove anything break out to avoid an infinite loop
234: if (!removedChars) {
235: break;
236: }
237: }
238:
239: // remove all double underscores
240: while (dbBuf.indexOf("__") > 0) {
241: dbBuf.deleteCharAt(dbBuf.indexOf("__"));
242: }
243:
244: while (dbBuf.length() > desiredLength) {
245: // still not short enough, get more aggressive
246: // don't remove the first segment, just remove the second over and over until we are short enough
247: int firstUs = dbBuf.indexOf("_");
248: if (firstUs > 0) {
249: int nextUs = dbBuf.indexOf("_", firstUs + 1);
250: if (nextUs > 0) {
251: //Debug.logInfo("couldn't shorten enough normally, removing second segment from " + dbBuf, module);
252: dbBuf.delete(firstUs, nextUs);
253: }
254: }
255: }
256:
257: //Debug.logInfo("Shortened " + dbName + " to " + dbBuf.toString(), module);
258: return dbBuf.toString();
259: }
260:
261: /**
262: * Converts a package name to a path by replacing all '.' characters with the File.separatorChar character.
263: * Is therefore platform independent.
264: * @param packageName The package name.
265: * @return The path name corresponding to the specified package name.
266: */
267: public static String packageToPath(String packageName) {
268: // just replace all of the '.' characters with the folder separater character
269: return packageName.replace('.', File.separatorChar);
270: }
271:
272: /**
273: * Replaces all occurances of oldString in mainString with newString
274: * @param mainString The original string
275: * @param oldString The string to replace
276: * @param newString The string to insert in place of the old
277: * @return mainString with all occurances of oldString replaced by newString
278: */
279: public static String replaceString(String mainString,
280: String oldString, String newString) {
281: return StringUtil.replaceString(mainString, oldString,
282: newString);
283: }
284:
285: public static String induceFieldType(String sqlTypeName,
286: int length, int precision,
287: ModelFieldTypeReader fieldTypeReader) {
288: if (sqlTypeName == null)
289: return "invalid";
290:
291: if (sqlTypeName.equalsIgnoreCase("VARCHAR")
292: || sqlTypeName.equalsIgnoreCase("VARCHAR2")
293: || (sqlTypeName.equalsIgnoreCase("CHAR") && length > 1)) {
294: if (length <= 10)
295: return "very-short";
296: if (length <= 60)
297: return "short-varchar";
298: if (length <= 255)
299: return "long-varchar";
300: return "very-long";
301: } else if (sqlTypeName.equalsIgnoreCase("TEXT")) {
302: return "very-long";
303: } else if (sqlTypeName.equalsIgnoreCase("INT")
304: || sqlTypeName.equalsIgnoreCase("SMALLINT")
305: || sqlTypeName.equalsIgnoreCase("DECIMAL")
306: || sqlTypeName.equalsIgnoreCase("NUMERIC")) {
307: if (length > 18 || precision > 6)
308: return "invalid-" + sqlTypeName + ":" + length + ":"
309: + precision;
310: if (precision == 0)
311: return "numeric";
312: if (precision == 2)
313: return "currency-amount";
314: if (precision <= 6)
315: return "floating-point";
316: return "invalid-" + sqlTypeName + ":" + length + ":"
317: + precision;
318: } else if (sqlTypeName.equalsIgnoreCase("BLOB")
319: || sqlTypeName.equalsIgnoreCase("OID")) {
320: return "blob";
321: } else if (sqlTypeName.equalsIgnoreCase("DATETIME")
322: || sqlTypeName.equalsIgnoreCase("TIMESTAMP")) {
323: return "date-time";
324: } else if (sqlTypeName.equalsIgnoreCase("DATE")) {
325: return "date";
326: } else if (sqlTypeName.equalsIgnoreCase("TIME")) {
327: return "time";
328: } else if (sqlTypeName.equalsIgnoreCase("CHAR") && length == 1) {
329: return "indicator";
330: } else {
331: return "invalid-" + sqlTypeName + ":" + length + ":"
332: + precision;
333: }
334: }
335: }
|