Java tutorial
/* * Copyright (C) 2014 Institute for Bioinformatics and Systems Biology, University Giessen, Germany * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.cebitec.readXplorer.util; import java.awt.Component; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.swing.JOptionPane; import org.apache.commons.lang3.StringEscapeUtils; import org.openide.util.NbBundle; /** * Contains general use utilities. * * @author -Rolf Hilker- */ public class GeneralUtils { /** * Calculates the percentage increase of value 1 to value 2. In case value1 is 0, * the percentage is set to 1.5 times the absolute difference as a weight factor. * @param value1 smaller value * @param value2 larger value * @return the percentage increase */ public static int calculatePercentageIncrease(int value1, int value2) { int percentDiff; if (value1 == 0) { int absoluteDiff = value2 - value1; percentDiff = (int) (absoluteDiff * 1.5); //weight factor } else { percentDiff = (int) Math.ceil(((double) value2 / (double) value1) * 100.0) - 100; } return percentDiff; } /** * @param parent the parent component * @return Any text found in the clipboard. If none is found, an empty * String is returned. */ public static String getClipboardContents(Component parent) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); String result = ""; Transferable contents = clipboard.getContents(null); final boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor); if (hasTransferableText) { try { result = (String) contents.getTransferData(DataFlavor.stringFlavor); } catch (UnsupportedFlavorException ex) { JOptionPane.showMessageDialog(parent, "Unsupported DataFlavor for clipboard copying.", "Paste Error", JOptionPane.ERROR_MESSAGE); } catch (IOException ex) { JOptionPane.showMessageDialog(parent, "IOException occured during recovering of text from clipboard.", "Paste Error", JOptionPane.ERROR_MESSAGE); } } return result; } /** * Checks if the input string is a valid number larger than 0. * @param input input string to check * @return <code>true</code> if it is a valid input string, <code>false</code> otherwise */ public static boolean isValidPositiveNumberInput(String input) { try { return Integer.parseInt(input) > 0; } catch (NumberFormatException e) { return false; } } /** * Checks if the input string is a valid number larger than or equal to 0. * @param input input string to check * @return <code>true</code> if it is a valid input * string, <code>false</code> otherwise */ public static boolean isValidNumberInput(String input) { try { return Integer.parseInt(input) >= 0; } catch (NumberFormatException e) { return false; } } /** * Checks if the input string is a valid position number between 1 and the * given maximum position. * @param input input string to check * @param max maximum position value for the input * @return <code>true</code> if it is a valid input string, * <code>false</code> otherwise */ public static boolean isValidPositionInput(String input, int max) { return GeneralUtils.isValidRangeInput(input, 1, max); } /** * Checks if the input string is a valid number in the range of the given * interval. * @param input input string to check * @param min minimum position value for the input * @param max maximum position value for the input * @return <code>true</code> if it is a valid input string, * <code>false</code> otherwise */ public static boolean isValidRangeInput(String input, int min, int max) { try { int tmp = Integer.parseInt(input); return tmp >= min && tmp <= max; } catch (NumberFormatException e) { return false; } } /** * Checks if the input string is a valid byte larger than or equal to 0. * @param text input string to check * @return <code>true</code> if it is a valid input string, * <code>false</code> otherwise */ public static boolean isValidByteInput(String text) { try { return Byte.parseByte(text) >= 0; } catch (NumberFormatException e) { return false; } } /** * Checks if the input string is a valid number between 1 and 100, so a valid * percentage value. * @param input input string to check * @return <code>true</code> if it is a valid percentage value, <code>false</code> otherwise */ public static boolean isValidPercentage(String input) { if (GeneralUtils.isValidPositiveNumberInput(input)) { int value = Integer.valueOf(input); if (value <= 100) { return true; } } return false; } /** * Calculates the given time as 3 entries in an array list: * 0 = hours, 1 = minutes, 2 = seconds. * @param timeInMillis given time in milliseconds * @return time as hours, minutes and seconds */ public static ArrayList<Integer> getTime(long timeInMillis) { ArrayList<Integer> timeList = new ArrayList<>(); int remdr = (int) (timeInMillis % (24L * 60 * 60 * 1000)); final int hours = remdr / (60 * 60 * 1000); remdr %= 60 * 60 * 1000; final int minutes = remdr / (60 * 1000); remdr %= 60 * 1000; final int seconds = remdr / 1000; timeList.add(0, hours); timeList.add(1, minutes); timeList.add(2, seconds); return timeList; } /** * Generates a string, which concatenates the list of strings for user friendly * displaying in the gui with an " and ". * @param strings the list of strings, which should be concatenated * @param maxLength maximum length of the string to return or 0, if no * restriction of the length is desired * @return the string containing all strings concatenated with "and". If the * string is too long it is cut at the maxLength position and "..." is * appended. */ public static String generateConcatenatedString(List<String> strings, int maxLength) { String concatString = implode(" and ", strings.toArray()); if (maxLength > 0 && concatString.length() > maxLength) { concatString = concatString.substring(0, maxLength).concat("..."); } return concatString; } /** * Deletes the given file and if existent also the corresponding ".bai" * index file. * @param lastWorkFile the file to delete * @return true, if the file could be deleted, false otherwise * @throws IOException */ public static boolean deleteOldWorkFile(File lastWorkFile) throws IOException { boolean deleted = false; if (lastWorkFile.canWrite()) { try { Files.delete(lastWorkFile.toPath()); deleted = true; File indexFile = new File(lastWorkFile.getAbsolutePath().concat(Properties.BAM_INDEX_EXT)); if (indexFile.canWrite()) { Files.delete(indexFile.toPath()); } } catch (IOException ex) { throw new IOException(NbBundle.getMessage(GeneralUtils.class, "MSG_GeneralUtils.FileDeletionError", lastWorkFile.getAbsolutePath())); } } return deleted; } /** * Joins array elements in a String. * @param delim Delimiter between each array element * @param array Array of elements * @return String */ public static String implode(String delim, Object[] array) { String asImplodedString; if (array.length == 0) { asImplodedString = ""; } else { StringBuilder sb = new StringBuilder(); sb.append(array[0]); for (int i = 1; i < array.length; i++) { sb.append(delim); sb.append(array[i]); } asImplodedString = sb.toString(); } return asImplodedString; } /** * Joins a map of elements in a String. * @param valueDelim Delimiter between key and value of an element * @param entryDelim Delimiter between each Entry element * @param map a map of elements * @return String */ public static String implodeMap(String valueDelim, String entryDelim, Map map) { String asImplodedString; if ((map == null) || (map.isEmpty())) { asImplodedString = ""; } else { StringBuilder sb = new StringBuilder(); Boolean firstLine = true; for (Iterator it = map.entrySet().iterator(); it.hasNext();) { if (!firstLine) { sb.append(entryDelim); } Map.Entry line = (Map.Entry) it.next(); sb.append(line.getKey()); sb.append(valueDelim); sb.append(line.getValue()); firstLine = false; } asImplodedString = sb.toString(); } return asImplodedString; } /** * Converts a given number into a number of the given classType. If this is * not possible, it throws a ClassCastException * @param <T> one of the classes derived from Number * @param classType the type to convert the number into * @param number the number to convert * @return The converted number */ public static <T extends Number> T convertNumber(Class<T> classType, Number number) throws ClassCastException { T convertedValue = null; if (classType.equals(Integer.class)) { convertedValue = classType.cast(number.intValue()); } else if (classType.equals(Double.class)) { convertedValue = classType.cast(number.doubleValue()); } else if (classType.equals(Long.class)) { convertedValue = classType.cast(number.longValue()); } else if (classType.equals(Float.class)) { convertedValue = classType.cast(number.floatValue()); } else if (classType.equals(Short.class)) { convertedValue = classType.cast(number.shortValue()); } else if (classType.equals(Byte.class)) { convertedValue = classType.cast(number.byteValue()); } if (convertedValue == null) { throw new ClassCastException("Cannot cast the given number into the given format."); } return convertedValue; } /** * format a number to show it to the user * @param number * @return a good readable string representation of the given number */ public static String formatNumber(Number number) { return NumberFormat.getInstance().format(number); } /** * Preliminary method for enshorting an Illumina based read name from single * or paired end to a still unique name, which can save memory. * Use with care! * @param readName the read name to enshorten * @return the short read name, if it was possible to shorten it. Otherwise * the original read name is returned */ public static String enshortenReadName(String readName) { String shortReadName = readName; String[] nameArray; if (readName.startsWith("@")) { nameArray = readName.split(":"); if (nameArray.length == 5) { shortReadName = nameArray[2] + nameArray[3] + nameArray[4]; if (shortReadName.contains("#")) { nameArray = shortReadName.split("#"); shortReadName = nameArray[0] + nameArray[1].split("/")[1]; } } else if (nameArray.length == 10) { shortReadName = nameArray[4] + nameArray[5] + nameArray[6]; } } return shortReadName; } public static String escapeHtml(String s) { return StringEscapeUtils.escapeHtml3(s); } /** * Enumeration of read name styles. */ public static enum NameStyle { /** Style useable for all reads. */ STYLE_STANDARD, /** Style useable for Illumina reads. */ STYLE_ILLUMINA; } /** * Splits the given readname by the given style. * @param readName The readname to split * @param specialStyle The style to use for splitting * @return The splitted read name array */ public static String[] splitReadName(String readName, NameStyle specialStyle) { String[] nameArray; if (specialStyle == NameStyle.STYLE_ILLUMINA) { nameArray = readName.split(":|#"); } else { int length = readName.length() / 5 + 1; nameArray = new String[length]; int index; int end; for (int i = 0; i < length; i++) { index = i * 5; end = index + 5; if (end < readName.length()) { nameArray[i] = readName.substring(index, end); } else { nameArray[i] = readName.substring(index, readName.length()); } } } return nameArray; } // /** // * For a given map of strings to other maps or objects, this method // * recursively adds or creates a mapping of the input array to the value to // * store. The depth of the HashMaps is dependent on the elements in the input // * array. The value to store is stored in the deepest level (leaf), which is // * hashed to the last element of the input array.<br>E.g. the read name arrays:<br> // * {HWI-ST486_0090, 5, 1101, 17454, 23711, ACTTGA/1}<br> // * {HWI-ST486_0090, 5, 1101, 17454, 23712, ACTTGA/1}<br> // * is transformed into a mapping of:<br> // * {HWI-ST486_0090{5, {1101, {17454, {23711, {ACTTGA/1, valueToStore}, {23712, {ACTTGA/1, valueToStore}}}}}}}<br> // * This method helps to significantly reduce the memory footprint for a huge amount of partially identical Strings. // * @param map The map (in)to which the new input shall be associated/integrated // * @param input The input array of Strings to integrate in the map // * @param valueToStore The value to store for the last element of the input // * array // * @return The updated map // */ // public static HashMap<String, Object> generateStringMap(HashMap<String, Object> map, String[] input, Object valueToStore) { // if (input.length > 1) { // String key = input[0]; // String[] next = new String[input.length - 1]; // System.arraycopy(input, 1, next, 0, input.length - 1); // if (!map.containsKey(key)) { // map.put(key, GeneralUtils.generateStringMap(new HashMap<String, Object>(), next, valueToStore)); // } else { // Object value = map.get(key); // if (value instanceof HashMap) { // @SuppressWarnings("unchecked") // HashMap<String, Object> subMap = (HashMap<String, Object>) value; // GeneralUtils.generateStringMap(subMap, next, valueToStore); // } else { // // } // } // } else if (input.length == 1) { // map.put(input[0], valueToStore); // } // return map; // } // // /** // * Convenience method for first splitting a read name and then storing it // * and the given valueToStore in the given map. // * @param map The map (in)to which the new input shall be associated/integrated // * @param readName The readname to split and store // * @param valueToStore The value to store for the last element of the // * splitted read name array // * @param style The style to use for splitting // */ // public static void splitReadNameAndAddToMap(HashMap<String, Object> map, String readName, Object valueToStore, NameStyle style) { // String[] splittedName = GeneralUtils.splitReadName(readName, style); // GeneralUtils.generateStringMap(map, splittedName, valueToStore); // } private GeneralUtils() { } }