/*************************************************************************** * Copyright 2006-2016 by Christian Ihle * * contact@kouchat.net * * * * This file is part of KouChat. * * * * KouChat is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version. * * * * KouChat is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with KouChat. * * If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ package net.usikkert.kouchat.util; import java.io.File; import java.io.UnsupportedEncodingException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.usikkert.kouchat.Constants; /** * A collection of static utility methods. * * @author Christian Ihle */ public final class Tools { private static final Logger LOG = Logger.getLogger(Tools.class.getName()); private static final Pattern VALID_NICK = Pattern.compile("[\\p{Alnum}[-_]]{1,10}"); /** * Private constructor. Only static methods here. */ private Tools() { } /** * Creates a timestamp in the format [HH:MM:SS]. * * @return The current time. */ public static String getTime() { final int h = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); final int m = Calendar.getInstance().get(Calendar.MINUTE); final int s = Calendar.getInstance().get(Calendar.SECOND); return "[" + getDoubleDigit(h) + ":" + getDoubleDigit(m) + ":" + getDoubleDigit(s) + "]"; } /** * Checks if a number is lower than 10, and creates a string with * a 0 added at the start if that is the case. Useful for clocks. * * @param number The number to check. * @return A string representation of the number. */ public static String getDoubleDigit(final int number) { if (number < 10) { return "0" + number; } else { return "" + number; } } /** * Converts a date to a string, in the format specified. * * @param d The date to convert to a string. * @param format The format to get the date in. * @return A converted date. * @see SimpleDateFormat */ public static String dateToString(final Date d, final String format) { String date = ""; final SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.ENGLISH); if (d == null) { date = formatter.format(new Date()); } else { date = formatter.format(d); } return date; } /** * Get a decimal number as a string, in the specified format. * * @param format The format to get the number. * @param number The number to add formatting to. * @return The formatted number. * @see DecimalFormat */ public static String decimalFormat(final String format, final double number) { final DecimalFormat formatter = new DecimalFormat(format); return formatter.format(number); } /** * Nick is valid if it consists of between 1 and 10 characters * of type [a-Z], [0-9], '-' and '_'. * * @param nick The nick to check. * @return If the nick is valid. */ public static boolean isValidNick(final String nick) { if (nick == null) { return false; } final Matcher m = VALID_NICK.matcher(nick); return m.matches(); } /** * Converts a number of bytes into megabytes or kilobytes, * depending on the size. * * @param bytes The number of bytes to convert. * @return A string representation of the bytes. */ public static String byteToString(final long bytes) { String size = ""; double kbSize = bytes / 1024.0; if (kbSize > 1024) { kbSize /= 1024; size = decimalFormat("0.00", kbSize) + "MB"; } else { size = decimalFormat("0.00", kbSize) + "KB"; } return size; } /** * Returns the number of bytes a String consists of. * * @param text The text to count the bytes in. * @return Number of bytes found in the text. */ public static int getBytes(final String text) { try { return text.getBytes(Constants.MESSAGE_CHARSET).length; } catch (final UnsupportedEncodingException e) { LOG.log(Level.SEVERE, e.toString(), e); return 0; } } /** * Calls {@link Thread#sleep(long)}, and ignores any exceptions. * * @param millis Number of milliseconds to sleep. */ public static void sleep(final long millis) { try { Thread.sleep(millis); } catch (final InterruptedException e) { LOG.log(Level.WARNING, e.toString()); } } /** * Capitalizes the first letter in a word. * * @param word The word to capitalize the first letter of. * @return The modified word. */ public static String capitalizeFirstLetter(final String word) { if (word == null) { return null; } if (word.length() == 0) { return word; } return word.substring(0, 1).toUpperCase() + word.substring(1); } /** * Shortens a word to the specified number of characters. * * @param word The word to shorten. * @param length The max number of characters for the word. * @return The modified word. */ public static String shorten(final String word, final int length) { if (word == null) { return null; } if (length < 0) { return ""; } if (word.length() <= length) { return word; } return word.substring(0, length); } /** * Gets the file extension from a file name. Including the separator dot. * * @param filename The file name to get the extension from. * @return The file extension, or <code>null</code> if file name is <code>null</code>. */ public static String getFileExtension(final String filename) { if (filename == null) { return null; } final int dotIndex = filename.lastIndexOf("."); if (dotIndex == -1) { return ""; } return filename.substring(dotIndex); } /** * Gets the base file name without the extension from a full file name. * Without the separator dot. * * @param filename The file name to get the base name from. * @return The base name, or <code>null</code> if file name is <code>null</code>. */ public static String getFileBaseName(final String filename) { if (filename == null) { return null; } final int dotIndex = filename.lastIndexOf("."); if (dotIndex == -1) { return filename; } return filename.substring(0, dotIndex); } /** * Finds how many percent a fraction is of the total. * * <p>Example: percent(50, 200) returns 25.</p> * * @param fraction The fraction of the total to find the percentage of. * @param total The total. * @return How many percent the fraction is of the total. */ public static double percent(final double fraction, final double total) { return (100.0 / total) * fraction; } /** * Finds the fraction from the percent of the total. * * <p>Example: percentOf(25, 200) returns 50.</p> * * @param percent How many percent of the total to get the fraction from. * @param total The total. * @return The fraction as percent of the total. */ public static double percentOf(final double percent, final double total) { return (percent / 100.0) * total; } /** * Add padding at the end of the stringToPad, until it reaches stringLength. * * @param stringToPad The string to add padding to. * @param paddedLength The length of the string, after padding. * @return The padded string. */ public static String postPadString(final String stringToPad, final int paddedLength) { final int missingPadding = paddedLength - stringToPad.length(); final StringBuilder paddedString = new StringBuilder(stringToPad); for (int i = 0; i < missingPadding; i++) { paddedString.append(" "); } return paddedString.toString(); } /** * Checks if the string is empty. It's considered empty if it's <code>null</code>, * zero length, or contains only spaces. * * @param string The string to check. * @return If the string is empty. */ public static boolean isEmpty(final String string) { return string == null || string.trim().isEmpty(); } /** * Appends the platform specific slash to the path, if missing. * * @param path The path to append the slash to. * @return The path, including a slash on the end. */ public static String appendSlash(final String path) { final String fileSeparator = System.getProperty("file.separator"); if (path.endsWith(fileSeparator)) { return path; } else { return path + fileSeparator; } } /** * Returns a new file with the same name and path as the existingFile, but with an incremented counter * at the end of the name. The name <code>file.txt</code> becomes <code>file_1.txt</code> if it's available. * If not, then the counter increments until a free name is found. * * <p>Returns the original file if it doesn't exist.</p> * * @param existingFile The (possibly) existing file to find a new free name for. * @return A new file, with a free, non existing name, or the same file if it doesn't exist. */ public static File getFileWithIncrementedName(final File existingFile) { Validate.notNull(existingFile, "The existing file to increment the name of can not be null"); if (!existingFile.exists()) { return existingFile; } int counter = 1; File newFile; final String path; if (existingFile.getParent() == null) { path = ""; } else { path = existingFile.getParent() + File.separator; } do { final String existingName = existingFile.getName(); final String newName = String.format("%s%s_%s%s", path, getFileBaseName(existingName), counter, getFileExtension(existingName)); newFile = new File(newName); counter++; } while (newFile.exists()); return newFile; } /** * Returns an empty string if the input is null. * * @param string The string to check. * @return An empty string if the input is null, or the input string if not. */ public static String emptyIfNull(final String string) { if (string == null) { return ""; } return string; } }