001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.utils;
042:
043: import java.text.SimpleDateFormat;
044: import java.util.ArrayList;
045: import java.util.Calendar;
046: import java.util.Date;
047: import java.util.ResourceBundle;
048:
049: /**
050: * Utility methods for String-related operations.
051: *
052: * @author Misha Dmitriev
053: * @author Ian Formanek
054: */
055: public class StringUtils {
056: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
057:
058: // -----
059: // I18N String constants
060: private static final ResourceBundle messages = ResourceBundle
061: .getBundle("org.netbeans.lib.profiler.utils.Bundle"); // NOI18N
062: private static final String THIS_WEEK_FORMAT = messages
063: .getString("StringUtils_ThisWeekFormat"); // NOI18N
064: private static final String LAST_WEEK_FORMAT = messages
065: .getString("StringUtils_LastWeekFormat"); // NOI18N
066: private static final String YESTERDAY_FORMAT = messages
067: .getString("StringUtils_YesterdayFormat"); // NOI18N
068: private static final String TODAY_FORMAT = messages
069: .getString("StringUtils_TodayFormat"); // NOI18N
070: private static final String OTHER_DAY_FORMAT = messages
071: .getString("StringUtils_OtherDayFormat"); // NOI18N
072: private static final String FULL_FORMAT = messages
073: .getString("StringUtils_FullFormat"); // NOI18N
074: // -----
075: private static SimpleDateFormat this WeekFormat = new SimpleDateFormat(
076: THIS_WEEK_FORMAT);
077: private static SimpleDateFormat lastWeekFormat = new SimpleDateFormat(
078: LAST_WEEK_FORMAT);
079: private static SimpleDateFormat yesterdayFormat = new SimpleDateFormat(
080: YESTERDAY_FORMAT);
081: private static SimpleDateFormat todayFormat = new SimpleDateFormat(
082: TODAY_FORMAT);
083: private static SimpleDateFormat otherFormat = new SimpleDateFormat(
084: OTHER_DAY_FORMAT);
085: private static SimpleDateFormat fullFormat = new SimpleDateFormat(
086: FULL_FORMAT);
087:
088: // ------------------------------------------------------------------------------------------------
089: // Varioius pretty-formating methods
090: // ------------------------------------------------------------------------------------------------
091: static StringBuffer tmpBuf = new StringBuffer();
092:
093: // ------------------------------------------------------------------------------------------------
094: // Various string conversion methods
095: // ------------------------------------------------------------------------------------------------
096: private static char[] strBuf;
097:
098: //~ Methods ------------------------------------------------------------------------------------------------------------------
099:
100: public static void appendSplittedLongString(StringBuffer sb,
101: String s, int maxLineLen) {
102: int nLines = (s.length() / maxLineLen)
103: + (((s.length() % maxLineLen) != 0) ? 1 : 0);
104: int idx = 0;
105:
106: for (int i = 0; i < nLines; i++) {
107: if (i > 0) {
108: sb.append('\n'); // NOI18N
109: }
110:
111: int endIdx = idx + maxLineLen;
112:
113: if (endIdx > s.length()) {
114: endIdx = s.length();
115: }
116:
117: sb.append(s.substring(idx, endIdx));
118: idx = endIdx;
119: }
120: }
121:
122: public static String[][] convertPackedStringsIntoStringArrays(
123: byte[] packedData, int[] packedArrayOffsets, int dim) {
124: String[][] ret = new String[dim][];
125: int len = packedArrayOffsets.length / dim;
126:
127: for (int i = 0; i < dim; i++) {
128: ret[i] = new String[len];
129: }
130:
131: int idx = 0;
132: int lastIdx = packedArrayOffsets.length - 1;
133:
134: for (int j = 0; j < len; j++) {
135: for (int i = 0; i < dim; i++) {
136: int utf8Len = (idx < lastIdx) ? (packedArrayOffsets[idx + 1] - packedArrayOffsets[idx])
137: : (packedData.length - packedArrayOffsets[idx]);
138: ret[i][j] = utf8ToString(packedData,
139: packedArrayOffsets[idx], utf8Len);
140: idx++;
141: }
142: }
143:
144: return ret;
145: }
146:
147: /** Used to print per cent figures with one digit after decimal point */
148: public static String floatPerCentToString(float t) {
149: tmpBuf.setLength(0);
150:
151: double floor = Math.floor(t);
152: double diff = t - floor;
153:
154: if (diff >= 0.95) {
155: floor = Math.round(t);
156: diff = 0.0;
157: }
158:
159: tmpBuf.append((int) floor);
160: tmpBuf.append('.'); // NOI18N
161: tmpBuf.append((int) Math.round(diff * 10));
162:
163: return tmpBuf.toString();
164: }
165:
166: // ------------------------------------------------------------------------------------------------
167: // Time/Date formatting
168: // ------------------------------------------------------------------------------------------------
169: public static String formatFullDate(Date date) {
170: return fullFormat.format(date);
171: }
172:
173: /** Formats provided time/date in a form that is tuned for user wrt to space needed and clarity/usefulness.
174: * It compareses the time/date passed against current time, and decides from one of 5 formats:
175: * - if the time is today, format it just using the time hh:mm:ss AM/PM
176: * - if the time is yesterday, format is as Yesterday, hh:mm AM/PM
177: * - if the time is this week, format is as [Name of Day], hh:mm AM/PM
178: * - if the time is last week, format is as Last [Name of Day], hh:mm AM/PM
179: * - otherwise format it as dd MMM yyyy
180: *
181: * @param date The date to format
182: * @return String with formatted time/date
183: */
184: public static String formatUserDate(Date date) {
185: Calendar now = Calendar.getInstance();
186: Calendar before = Calendar.getInstance();
187: before.setTime(date);
188:
189: if (before.getTimeInMillis() <= now.getTimeInMillis()) { // the time is indeed in the past
190:
191: int daysDelta = getDaysDifference(before, now);
192:
193: if (daysDelta == 0) {
194: // today
195: return todayFormat.format(date);
196: } else if (daysDelta == 1) {
197: // yesterday
198: return yesterdayFormat.format(date);
199: } else {
200: int weekDelta = getWeekDifference(before, now);
201:
202: if (weekDelta == 0) {
203: // this week
204: return this WeekFormat.format(date);
205: } else if (weekDelta == 1) {
206: //last week
207: return lastWeekFormat.format(date);
208: }
209: }
210: }
211:
212: return otherFormat.format(date);
213: }
214:
215: /** Represent time (given in microsecond) in milliseconds, with roughly the same number of meaningful digits */
216: public static String mcsTimeToString(long t) {
217: tmpBuf.setLength(0);
218:
219: if (t >= 100000) {
220: return Long.toString(t / 1000);
221: } else if (t >= 10000) {
222: long x = t / 1000;
223: tmpBuf.append(Long.toString(x));
224: tmpBuf.append('.');
225: tmpBuf.append(Long.toString((t - (x * 1000)) / 100));
226:
227: return tmpBuf.toString();
228:
229: //return Long.toString(x) + "." + Long.toString((t - x*1000) / 100);
230: } else if (t >= 1000) {
231: long x = t / 1000;
232: tmpBuf.append(Long.toString(x));
233: tmpBuf.append('.');
234: tmpBuf.append(Long.toString((t - (x * 1000)) / 10));
235:
236: return tmpBuf.toString();
237:
238: //return Long.toString(x) + "." + Long.toString((t - x*1000) / 10);
239: } else {
240: if (t >= 100) {
241: tmpBuf.append("0."); // NOI18N
242: } else if (t >= 10) {
243: tmpBuf.append("0.0"); // NOI18N
244: } else {
245: tmpBuf.append("0.00"); // NOI18N
246: }
247:
248: return (tmpBuf.append(Long.toString(t))).toString();
249: }
250: }
251:
252: /** Represents the given number of bytes as is, or as "xxx K" (if >= 100 KBytes), or as "xxx M" (if >= 100 MBytes) */
253: public static String nBytesToString(long b) {
254: tmpBuf.setLength(0);
255:
256: if (b < (100 * 1024)) {
257: return Long.toString(b) + " B"; // NOI18N
258: } else if (b < (100 * 1024 * 1024)) {
259: long k = b >> 10;
260: tmpBuf.append(Long.toString(k));
261:
262: if (b < (100 * 1024 * 1024)) {
263: tmpBuf.append('.'); // NOI18N
264: tmpBuf.append(Long.toString((b - (k << 10)) / 102)); // 102 stands for 1/10th of 1K
265: }
266:
267: tmpBuf.append(" KB"); // NOI18N
268:
269: return tmpBuf.toString();
270: } else {
271: long m = b >> 20;
272: tmpBuf.append(Long.toString(m));
273:
274: if (b < 10737418240L) {
275: tmpBuf.append('.'); // NOI18N
276: tmpBuf.append(Long.toString((b - (m << 20)) / 104858)); // 104858 stands for 1/10th of 1M
277: }
278:
279: tmpBuf.append(" MB"); // NOI18N
280:
281: return tmpBuf.toString();
282: }
283: }
284:
285: // ------------------------------------------------------------------------------------------------
286: // Miscellaneous
287: // ------------------------------------------------------------------------------------------------
288: public static String[] parseArgsString(String args) {
289: if (args == null) {
290: return new String[0];
291: }
292:
293: ArrayList listRes = new ArrayList();
294:
295: int pos0 = 0;
296: int len = args.length();
297:
298: while (pos0 < len) {
299: int pos1 = pos0;
300:
301: while ((pos1 < len) && (args.charAt(pos1) != ' ')
302: && (args.charAt(pos1) != 8)) {
303: pos1++; // NOI18N
304: }
305:
306: listRes.add(args.substring(pos0, pos1));
307: pos0 = pos1 + 1;
308:
309: while ((pos0 < len)
310: && ((args.charAt(pos0) == ' ') || (args
311: .charAt(pos0) == 8))) {
312: pos0++; // NOI18N
313: }
314: }
315:
316: return (String[]) listRes.toArray(new String[listRes.size()]);
317: }
318:
319: public static String userFormClassName(String className) {
320: if (className == null) {
321: return null;
322: }
323:
324: className = className.replace('/', '.'); // NOI18N
325:
326: if (className.startsWith("[")) { // NOI18N
327:
328: String elemType = null;
329: int lastBrackPos = className.lastIndexOf('['); // NOI18N
330:
331: if (lastBrackPos == (className.length() - 2)) { // It's an array of ultimately primitive type, e.g. [[C
332:
333: switch (className.charAt(lastBrackPos + 1)) {
334: case 'C':
335: elemType = "char";
336:
337: break; // NOI18N
338: case 'B':
339: elemType = "byte";
340:
341: break; // NOI18N
342: case 'I':
343: elemType = "int";
344:
345: break; // NOI18N
346: case 'Z':
347: elemType = "boolean";
348:
349: break; // NOI18N
350: case 'F':
351: elemType = "float";
352:
353: break; // NOI18N
354: case 'D':
355: elemType = "double";
356:
357: break; // NOI18N
358: case 'S':
359: elemType = "short";
360:
361: break; // NOI18N
362: case 'J':
363: elemType = "long";
364:
365: break; // NOI18N
366: }
367: } else {
368: elemType = className.substring(lastBrackPos + 1);
369: }
370:
371: int nDims = lastBrackPos + 1;
372: tmpBuf.setLength(0);
373: tmpBuf.append(elemType);
374:
375: for (int i = 0; i < nDims; i++) {
376: tmpBuf.append("[]"); // NOI18N
377: }
378:
379: return tmpBuf.toString();
380: } else {
381: return className;
382: }
383: }
384:
385: public static String utf8ToString(byte[] src, int stPos, int utf8Len) {
386: if ((strBuf == null) || (strBuf.length < utf8Len)) {
387: strBuf = new char[utf8Len];
388: }
389:
390: int i = stPos;
391: int j = 0;
392: int limit = stPos + utf8Len;
393:
394: while (i < limit) {
395: int b = src[i++] & 255;
396:
397: if (b >= 224) {
398: b = (b & 15) << 12;
399: b = b | ((src[i++] & 63) << 6);
400: b = b | (src[i++] & 63);
401: } else if (b >= 192) {
402: b = (b & 31) << 6;
403: b = b | (src[i++] & 63);
404: }
405:
406: strBuf[j++] = (char) b;
407: }
408:
409: return (new String(strBuf, 0, j)).intern();
410: }
411:
412: private static int getDaysDifference(Calendar before, Calendar after) {
413: int diff = after.get(Calendar.DAY_OF_YEAR)
414: - before.get(Calendar.DAY_OF_YEAR);
415: diff = diff
416: + (before.getMaximum(Calendar.DAY_OF_YEAR) * (after
417: .get(Calendar.YEAR) - before.get(Calendar.YEAR)));
418:
419: return diff;
420: }
421:
422: private static int getWeekDifference(Calendar before, Calendar after) {
423: int diff = after.get(Calendar.WEEK_OF_YEAR)
424: - before.get(Calendar.WEEK_OF_YEAR);
425: diff = diff
426: + (before.getMaximum(Calendar.WEEK_OF_YEAR) * (after
427: .get(Calendar.YEAR) - before.get(Calendar.YEAR)));
428:
429: return diff;
430: }
431: }
|