Util.java [src/usda/weru/util] Revision: default  Date:
package usda.weru.util;


import java.io.*;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import usda.weru.weps.RegPanel;

/**
 * Class containing utility functions used by Weps.
 * 
 * @author wjr
 * @version 1.0
 */
public class Util {

    private static final Logger LOGGER = Logger.getLogger(Util.class.getName());

    public static final int MAX_WINDOWS_FILEPATH_LENGTH=255;
//    /**
//     * Used to set the focus on a particular field.
//     * Must be used in error checking code since the 
//     * main dispatching thread changes focus after 
//     * any user specified code is executed.
//     * 
//     * @param c A swing component (JTextField, etc.) that can accept 
//     * the focus.
//     */
//    public static void setFocus(JComponent c) {
//        SwingUtilities.invokeLater(new FocusGrabber(c));
////		SwingUtilities.invokeLater(new this(c));
//    }
//
//    /**
//     * Runnable class used by Util.setFocus().
//     * 
//     * @author wjr
//     * @version 1.0
//     */
//    private static class FocusGrabber implements Runnable {
//
//        JComponent component;
//
//        public FocusGrabber(JComponent component) {
//            this.component = component;
//        }
//
//        public void run() {
//            component.grabFocus();
////			component.requestFocus();
////			component.requestFocusInWindow();
//        }
//    }
//
//    public static File resolveFileAsRelativeChildOrAbsolute(File parent, File file){
//        String path = file.getAbsolutePath();
//        String topPath = parent.getAbsolutePath();
//        if(path.startsWith(topPath) && path.length() > topPath.length()){
//               path = path.substring(topPath.length() + 1);
//               return new File(path);
//        }
//        else{
//            return new File(file.getAbsoluteFile());
//        }
//    }
//
//    public static boolean deleteAll(File file) {
//        return deleteAll(file, null);
//    }
//
//    public static boolean deleteAll(File file, List<File> lockedFiles) {
//        List<File> failedToDelete = new LinkedList <File> ();
//        if (file.isDirectory()) {
//            for (File child : file.listFiles(file.getArchiveDetector())) {
//                boolean success = deleteAll(child, lockedFiles);
//                if (!success) {
//                    //Didn't delete on the first pass, try again.
//                    failedToDelete.add(child);
//                }
//            }
//
//            //now loop over for a second pass
//            Iterator<File> i = failedToDelete.iterator();
//            while(i.hasNext()){
//                File child = i.next();
//                boolean deleted = deleteAll(child, lockedFiles);
//                if(deleted){
//                    i.remove();
//                }
//                 else{
//                    LOGGER.error("Unable to delete: " + child.getAbsolutePath());
//                    
//                    //last chance, try and delete on exit.
//                    child.deleteOnExit();
//                 }
//            }
//
//            //if we're tracking the locked files include them.
//            if(lockedFiles != null){
//                lockedFiles.addAll(failedToDelete);
//            }
//
//        }
//        // The file is now empty so delete it   
//        boolean deleted = file.delete();
//        if(!deleted){
//            file.deleteOnExit();
//        }
//        return deleted;
//    }
//
//    public static boolean copyDirectory(File from, File to, boolean purge) {
//
//        //Remove the file if it exists and purging is true.
//        if (to.exists() && purge) {
//            boolean removed = deleteAll(to);
//            if (!removed) {
//                LOGGER.error("unable to purge directory: \"" + to.getAbsolutePath() + "\"");
//                return false;
//            }
//        }
//
//        if (from.isDirectory()) {
//            if (!to.exists()) {
//                boolean created = to.mkdirs();
//                if (!created) {
//                    LOGGER.error("unable to create directory: \"" + to.getAbsolutePath() + "\"");
//                    return false;
//                }
//            }
//            java.io.File[] children = from.listFiles();
//            for (java.io.File child : children) {
//                File childFrom = new File(child);
//                File childTo = new File(to, child.getName());
//                boolean copied = copyDirectory(childFrom, childTo, purge);
//                if (!copied) {
//                    LOGGER.error("unable to copy file: \"" + childTo.getAbsolutePath() + "\"");
//                    return false;
//                }
//            }
//        } else {
//            boolean copied = copyFile(from, to);
//            if (!copied) {
//                LOGGER.error("unable to copy file: \"" + to.getAbsolutePath() + "\"");
//                return false;
//            }
//        }
//
//        return true;
//    }
//
    public static boolean copyFile(String fromFile, String toFile) {
        return copyFile(new File(fromFile), new File(toFile));
    }

    public static boolean copyFile(File from, File to) {
        if (from.exists() && from.isFile()) {
            if (from.getAbsoluteFile().equals(to.getAbsoluteFile())) {
                //System.err.println("ERROR copyFile: can't copy file from its own!");
                return false;
            }
            File dir = (File) to.getParentFile();
            if (!dir.isDirectory()) {
                boolean created = dir.mkdirs();
                if (!created) {
                    LOGGER.severe("Unable to created required directory structure: " + to.getParentFile().getAbsolutePath());
                    return false;
                }
            }
            byte buffer[] = new byte[(int) 100000];
            FileInputStream fromReader = null;
            FileOutputStream toWriter = null;
            try {
                fromReader = new FileInputStream(from);
                toWriter = new FileOutputStream(to);
                int byteRead = 0;
                while ((byteRead = fromReader.read(buffer)) != -1) {
                    toWriter.write(buffer, 0, byteRead);
                    toWriter.flush();
                }

            } catch (Exception e) {
                //System.err.println("error: copy file");
                e.printStackTrace();
                return false;
            } finally {
                try {
                    fromReader.close();
                } catch (Exception e) {
                    LOGGER.severe("Error closing file stream " + e.getMessage());
                }

                try {
                    toWriter.close();
                } catch (Exception e) {
                    LOGGER.severe("Error closing file stream " + e.getMessage());
                }

            }
            return true;
        } else {
            return false;
        }
    }
    public static final double OneFootInMeters = 0.3048;
    public static final double OneMileInKM = 5280 * OneFootInMeters / 1000;
    public static final double SquareFeetInAcre = 43560.;

//    public static String calculateArea(JTextField jtf1, JTextField jtf2, String units) {
//
//        String area = "";
//        String s1 = jtf1.getText().trim();
//        String s2 = jtf2.getText().trim();
//
//
//        double val1 = Double.parseDouble(s1);
//        double val2 = Double.parseDouble(s2);
//
//        try {
//            if (s1.equals("") || s2.equals("")) {
//                //System.err.println("U_cA: The String was Empty in Calc AREA ");
//            } else if (!(val1 > 0 || val2 > 0)) {
//                //System.err.println("U_cA: Cannot calculate the AREA. The values are less than Zero");
//            } else {
//                //Changed the fraction digits from 0 to 2
//                area = calculateArea(s1, s2, units, 2);
//            }
//        } catch (NumberFormatException e) {
//            //System.err.println("In calculate AREA Exception occured " + e);
//        }
//        return area;
//    }
//
    public static String calculateArea(String txt1,
            String txt2, String units, int numDigits) {

        double a1 = 0;
        double a2 = 0;
        String myArea = "";

        if (!(txt1.equals("") || txt2.equals(""))) {
            try {
                a1 = new Double(txt1).doubleValue();
                a2 = new Double(txt2).doubleValue();
            } catch (NumberFormatException e) {
                //System.err.println("U_cA: The String was Empty " + e);
                // not an error; blank lines are OK
            }

            if (!(a1 > 0 || a2 > 0)) {
                return myArea;
            } else {
                double area = a1 * a2;

                if (units.equals(Util.USUnits)) {
                    area /= SquareFeetInAcre;
                } else {
                    area /= 10000.;
                }
                NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
                nf.setMaximumFractionDigits(numDigits);
                nf.setGroupingUsed(false);
                myArea = nf.format(area);
            }
        }
//			//System.out.println("Value of the area 4 ARGUMENTS is " + myArea);
        return myArea;
    }

    public static final String calculateArea(String txt1,
            String txt2, String units) {

        double a1 = 0;
        double a2 = 0;

        try {
            a1 = new Double(txt1).doubleValue();
            a2 = new Double(txt2).doubleValue();
        } catch (NumberFormatException e) {
//			//System.err.println("cA: " + e);
            // not an error; blank lines are OK
        }
        double area = a1 * a2;

        if (units.equals(Util.USUnits)) {
            area /= SquareFeetInAcre;
        } else {
            area /= 10000.;
        }
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        nf.setMaximumFractionDigits(2);
        nf.setGroupingUsed(false);
//		//System.out.println("Value of the area STRING 3 ARGUMENTS is " + nf.format(area));
        return nf.format(area);

    }

    public static final String calculateArea(double a1, double a2, String units) {
        //Changed the fraction digits from 0 to 2
        return Util.calculateArea(a1, a2, units, 2, RegPanel.SHAPE_RECTANGLE);
    }

    public static final String calculateArea(double a1,
            double a2, String units, int numDigits) {
        return calculateArea(a1, a2, units, numDigits, RegPanel.SHAPE_RECTANGLE);
    }

    public static final String calculateArea(double a1,
            double a2, String units, int numDigits, String shape) {

        double area = a1 * a2;

        if (shape.equals(RegPanel.SHAPE_RECTANGLE)) {
        } else if (shape.equals(RegPanel.SHAPE_SQUARE)) {
        } else if (shape.equals(RegPanel.SHAPE_CIRCLE)) {
        } else if (shape.startsWith("half_circle")) {
            area = area / 2;
        } else if (shape.startsWith("quarter_circle")) {
            area = area / 4;
        }

        if (units.equals(Util.USUnits)) {
            area /= SquareFeetInAcre;
            area /= OneFootInMeters * OneFootInMeters;
        } else {
            area /= 10000.;
        }
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        nf.setMaximumFractionDigits(numDigits);
        nf.setGroupingUsed(false);
//		//System.out.println("Value of the area DOUBLE 3 ARGUMENTS is " + nf.format(area));
        return nf.format(area);

    }
    public static final String USUnits = "US";
    public static final String SIUnits = "SI";
    public static final String NoUnits = "No";

    public static final String convertFeetToMeters(String arg,
            String units) {
        //Changed the fraction digits from 0 to 2
        return convertFeetToMeters(arg, units, 2);
    }

    public static final String convertFeetToMeters(String arg,
            String units, int sigDigits) {
        if (units.equals(USUnits) || units.equals(NoUnits)) {
            return arg;
        }
        double val = 0.0;
        try {
            val = new Double(arg).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("cFTM: error converting feet to meters" + e);
        }
        val *= OneFootInMeters;
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        nf.setMaximumFractionDigits(sigDigits);
        nf.setMinimumFractionDigits(sigDigits);
        nf.setGroupingUsed(false);
        return nf.format(val);
    }

    public static final String convertMilesToKM(String arg,
            String units) {
        if (units.equals(USUnits) || units.equals(NoUnits)) {
            return arg;
        }
        double val = 0.0;
        try {
            val = new Double(arg).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("cFTM: error converting feet to meters" + e);
        }
        val *= OneMileInKM;
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        //Changed the fraction digits from 1 to 2
        nf.setMaximumFractionDigits(2);
        nf.setGroupingUsed(false);
        return nf.format(val);
    }

    public static final String convertMetersToFeet(String arg,
            String units) {
        //Changed the fraction digits from 0 to 2
        return convertMetersToFeet(arg, units, 2);
    }

    public static final String convertKMToMiles(String arg,
            String units) {
        //Changed the fraction digits from 0 to 2
        return convertKMToMiles(arg, units, 2);
    }

    public static final String convertMetersToFeet(String arg,
            String units, int maxDigits) {
        if (units.equals(SIUnits) || units.equals(NoUnits)) {
            return arg;
        }
        double val = 0.0;
        try {
            val = new Double(arg).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("U_cMTF: error converting meters to feet" + e);
        }
        val /= OneFootInMeters;
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        nf.setMaximumFractionDigits(maxDigits);
        nf.setMinimumFractionDigits(maxDigits);
        nf.setGroupingUsed(false);
        return nf.format(val);
    }

    public static final String convertMetersToFeetAndFormat(String arg,
            String units, int maxDigits) {
        double val = 0.0;
        try {
            val = new Double(arg).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("cFTM: error converting meters to feet" + e);
        }
        if (units.equals(USUnits)) {
            val /= OneFootInMeters;
        }
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        nf.setMaximumFractionDigits(maxDigits);
        nf.setMinimumFractionDigits(maxDigits);
        nf.setGroupingUsed(false);
        return nf.format(val);
    }

    public static final String convertKMToMiles(String arg,
            String units, int maxDigits) {
        if (units.equals(SIUnits) || units.equals(NoUnits)) {
            return arg;
        }
        double val = 0.0;
        try {
            val = new Double(arg).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("cFTM: error converting meters to feet" + e);
        }
        val /= OneMileInKM;
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        nf.setMaximumFractionDigits(maxDigits);
        nf.setGroupingUsed(false);
        return nf.format(val);
    }

    public static final String convertMetersToFeet(double arg,
            String units) {
        //Changed the fraction digits from 0 to 2
        return convertMetersToFeet(arg, units, 2);
    }

    public static final String convertKMToMiles(double arg,
            String units) {
        //Changed the fraction digits from 0 to 2
        return convertKMToMiles(arg, units, 2);
    }

    public static final String convertMetersToFeet(double arg,
            String units, int maxDigits) {
        if (units.equals(Util.USUnits)) {
            arg /= OneFootInMeters;
        }

        try {
            NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
            //Commenting out because the maximum fraction digits is set to 2 irrespective of US units or SI units.
            //nf.setMaximumFractionDigits(maxDigits + (units.equals(Util.USUnits) ? 0 : 1));
            nf.setMaximumFractionDigits(maxDigits);
            nf.setGroupingUsed(false);
            return nf.format(arg);
        } catch (NumberFormatException e) {
            //System.out.println("Util_convertMetersToFeet Ln:357 Error :" + e );
            return "";
        }

    }

    public static double convertBetweenFeetAndMeters(Double value, String fromUnits) {
        if (fromUnits.equals(Util.USUnits)) {
            //In US Units, convert to meters
            return value * OneFootInMeters;
        } else {
            //In SI Units, convert to feet
            return value / OneFootInMeters;
        }
    }

    public static final String convertKMToMiles(double arg,
            String units, int maxDigits) {
        if (units.equals(Util.USUnits)) {
            arg /= OneMileInKM;
        }
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        nf.setMaximumFractionDigits(maxDigits +
                (units.equals(Util.USUnits) ? 0 : 1));
        nf.setGroupingUsed(false);
        return nf.format(arg);
    }

//    public static void checkNumericJTF(Component parent,
//            JTextField jtf,
//            double val,
//            String prop,
//            PropertyChangeSupport changes,
//            String measurementUnits) {
//
//        //Changed the fraction digits from 0 to 2
//        checkNumericJTF(parent, jtf, val, prop, changes, measurementUnits, 2);
//    }
//
//    public static void checkBigNumericJTF(Component parent,
//            JTextField jtf,
//            double val,
//            String prop,
//            PropertyChangeSupport changes,
//            String measurementUnits) {
//
//        //Changed the fraction digits from 0 to 2
//        checkBigNumericJTF(parent, jtf, val, prop, changes, measurementUnits, 2);
//    }
//
//    public static void checkNumericJTF(Component parent,
//            JTextField jtf,
//            double val,
//            String prop,
//            PropertyChangeSupport changes,
//            String measurementUnits,
//            double loBound,
//            double hiBound) {
//
//        //Changed the fraction digits from 0 to 2 - "numDigits" value
//        checkNumericJTF(parent, jtf, val, prop, changes, measurementUnits, 2,
//                loBound, hiBound);
//    }
//
//    public static void checkNumericJTF(Component parent,
//            JTextField jtf,
//            double val,
//            String prop,
//            PropertyChangeSupport changes,
//            String measurementUnits,
//            int numDigits) {
//
//        checkNumericJTF(parent, jtf, val, prop, changes, measurementUnits, numDigits,
//                -(Double.MAX_VALUE - 1), Double.MAX_VALUE);
////						Double.MIN_VALUE, Double.MAX_VALUE);
//    }
//
//    public static void checkBigNumericJTF(Component parent,
//            JTextField jtf,
//            double val,
//            String prop,
//            PropertyChangeSupport changes,
//            String measurementUnits,
//            int numDigits) {
//
//        checkBigNumericJTF(parent, jtf, val, prop, changes, measurementUnits, numDigits,
//                Double.MIN_VALUE, Double.MAX_VALUE);
//    }
//
//    public static void checkNumericJTF(Component parent,
//            JTextField jtf,
//            double val,
//            String prop,
//            PropertyChangeSupport changes,
//            String measurementUnits,
//            int numDigits,
//            double loBound,
//            double hiBound) {
//
//////System.out.println("U_cN: " + jtf.getText());		
//        try {
//            double xtemp = 0.0;
//////System.out.println("U_cN: fire 3");
//
//            if (jtf.getText().trim().length() != 0) {
//                xtemp = Double.parseDouble(jtf.getText());
//            }
//////System.out.println("U_cN: fire 4 " + xtemp + " " + loBound + " " + hiBound);
//            if (xtemp < loBound && loBound != hiBound) {
////				JOptionPane.showMessageDialog(parent,
////											  "Number specified is too small\n" +
////											  "must be greater than " + loBound,
////											  "Number out of range",
////											  JOptionPane.ERROR_MESSAGE);
////				jtf.setText(Util.convertMetersToFeet(val, measurementUnits));
//                jtf.setText(Util.convertMetersToFeet(loBound, measurementUnits));
////				Util.setFocus(jtf);
//                return;
//            }
//////System.out.println("U_cN: fire 2");
//            if (xtemp > hiBound && loBound != hiBound) {
////				JOptionPane.showMessageDialog(parent,
////											  "Number specified is too large\n" +
////											  "must be less than " + hiBound,
////											  "Number out of range",
////											  JOptionPane.ERROR_MESSAGE);
////				jtf.setText(Util.convertMetersToFeet(val, measurementUnits));
//                jtf.setText(Util.convertMetersToFeet(hiBound, measurementUnits));
////				Util.setFocus(jtf);
//                return;
//            }
//////System.out.println("U_cN: fire 1");
//            if (measurementUnits.equals(Util.USUnits)) {
//                xtemp *= OneFootInMeters;
//            }
//            if (xtemp != 0 && Math.abs((xtemp - val) / xtemp) < 0.001) {
//                return;
//            }
//// Use SIUnits since we are in meters no matter what is being displayed
//            String temp = Util.convertMetersToFeet(xtemp, Util.SIUnits, numDigits);
//////System.out.println("U_cN: fire");
//            if (changes != null) {
//                changes.firePropertyChange(prop, null, temp);
//            }
//        } catch (NumberFormatException k) {
////			JOptionPane.showMessageDialog(parent,
////										  "Invalid number format",
////										  "Invalid number",
////										  JOptionPane.ERROR_MESSAGE);
//            jtf.setText(Util.convertMetersToFeet(val, measurementUnits));
////			Util.setFocus(jtf);
//        }
//    //       //System.out.println("Util:checkNumericJTF:value changed to"+jtf.getText());
//    }
//
//    public static void checkBigNumericJTF(Component parent,
//            JTextField jtf,
//            double val,
//            String prop,
//            PropertyChangeSupport changes,
//            String measurementUnits,
//            int numDigits,
//            double loBound,
//            double hiBound) {
//
//////System.out.println("U_cBNJTF: " + jtf.getText());		
//        try {
//            double xtemp = 0.0;
//            if (jtf.getText().trim().length() != 0) {
//                xtemp = Double.parseDouble(jtf.getText());
//            }
//            if (measurementUnits.equals(Util.USUnits)) {
//                xtemp *= OneMileInKM;
//            }
//////System.out.println("U_cBNJTF: xtemp " + xtemp);
//            if (xtemp != 0 && Math.abs((xtemp - val) / xtemp) < 0.001) {
//                return;
//            }
//// Use SIUnits since we are in meters no matter what is being displayed
//            String temp = Util.convertKMToMiles(xtemp, Util.SIUnits, numDigits);
//////System.out.println("U_cBNJFT: temp " + temp);			
//            if (changes != null) {
//                changes.firePropertyChange(prop, null, temp);
//            }
//        } catch (NumberFormatException k) {
////			JOptionPane.showMessageDialog(parent,
////										  "Invalid number format",
////										  "Invalid number",
////										  JOptionPane.ERROR_MESSAGE);
//            jtf.setText(Util.convertKMToMiles(val, measurementUnits));
////			Util.setFocus(jtf);
//        }
//    }
//
    static String getRelativePath(String filPath, String relPath) {
        try {
            filPath = new File(filPath).getCanonicalPath();
            relPath = new File(relPath).getCanonicalPath();
        } catch (IOException e) {
            //System.err.println("U_gRP: " + e);
            return filPath;
        }
        if (!filPath.startsWith(relPath)) {
            return filPath;
        } else {
            return filPath.substring(relPath.length() + 1);
        }
    }

//    public static Hashtable<String, String> loadToolTipsTable(File file) {
//        java.util.Hashtable ht = new java.util.Hashtable();
//
//        try {
//            BufferedReader in = new BufferedReader(new FileReader(file));
//            String temp;
//            while ((temp = in.readLine()) != null) {
//                StringTokenizer st = new StringTokenizer(temp, "=");
//                if (st.countTokens() < 2) {
//                    continue;
//                }
//                String id = st.nextToken().trim();
//                try {
//                    StringBuffer sb = new StringBuffer(st.nextToken());
//                    while (st.hasMoreTokens()) {
//                        sb.append("=" + st.nextToken());
//                    }
//                    ht.put(id, sb.toString().trim());
//                } catch (java.util.NoSuchElementException e) {
//                    // skip invalid lines - comments or nothing after =
//                }
//            }
//            in.close();
//        } catch (IOException e) {
//            //System.err.println("Unable to load tooltips file");
//        }
//
//
//        return ht;
//    }
//
//    public static void loadToolTips(/*JFrame*/Container topLevel, File inputFile) {
//        java.util.Hashtable ht = loadToolTipsTable(inputFile);
//        Component[] components;
//
//
//
//        if (topLevel instanceof JDialog) {
//            topLevel = (JDialog) topLevel;
//            if (((JDialog) topLevel).getJMenuBar() != null) {
//                loadToolTips(((JDialog) topLevel).getJMenuBar(), ht);
//            }
//            components = ((JDialog) topLevel).getContentPane().getComponents();
//        } else if (topLevel instanceof JFrame) {
//            topLevel = (JFrame) topLevel;
//            if (((JFrame) topLevel).getJMenuBar() != null) {
//                loadToolTips(((JFrame) topLevel).getJMenuBar(), ht);
//            }
//            components = ((JFrame) topLevel).getContentPane().getComponents();
//
//        } else {
//            //if the container is not a frame or a dialog or a filechooser, then return
//            //System.err.println("Util-loadToolTips:The parent container is neither a JFrame nor a JDialog");
//            //System.err.println("Util-loadToolTips:Tool tips are not activated");
//            return;
//        }
//
//
//        for (int cdx = 0; cdx < components.length; cdx++) {
//            if (components[cdx] instanceof Container) {
//                loadToolTips(/*(JPanel)*/(Container) components[cdx], ht);
//            } else {
////				//System.out.println(" is not Container");
//            }
//        }
//    }
//
//    static String className(JComponent jcomp) {
//        String name = jcomp.getClass().toString();
//        return name.substring(name.lastIndexOf(".") + 1);
//    }
//
    static String cvtKeyStroke(javax.swing.KeyStroke inpk) {
        if (inpk == null) {
            return null;
        }
        String inp = inpk.toString();
        if (inp == null) {
            return inp;
        }
        inp = inp.substring(8);
        inp = inp.substring(0, inp.length() - 2);
        return inp;
    }

//    /**
//     * Finds the containing frame to anchor JOptionPanes
//     */
//    public static JFrame getParentJFrame(Component j) {
//        for (; j.getParent() != null; j = j.getParent()) {
//            ;
//        }
//        return (JFrame) j;
//    }
//
//    static void printComponent(JComponent jcomp, java.util.Hashtable ht) {
//        String tooltip = jcomp.getToolTipText();
////		//System.out.println("lC2: " + tooltip + "=");
//        boolean printFlg = false;  // comment out the print statements
//        if (printFlg) {
//            if (jcomp instanceof JPanel) {
//                //System.err.println("lC: |"  + className(jcomp) + " | " +
//                //							   tooltip);
//            } else if (jcomp instanceof JMenuItem) {
////				//System.err.println("lC: |" + className(jcomp) + " | " +
////								   tooltip + " | " +
////								   ((JMenuItem) jcomp).getText() + " | " +
////								   (char) ((JMenuItem) jcomp).getMnemonic() + " | " +
////								   cvtKeyStroke(((JMenuItem) jcomp).getAccelerator()));
//            } else if (jcomp instanceof AbstractButton) {
////				//System.err.println("lC: |" + className(jcomp) + " | " +
////								   tooltip + " | " +
////								   ((AbstractButton) jcomp).getText() + " | " +
////								   (char) ((AbstractButton) jcomp).getMnemonic());
//            } else if (jcomp instanceof JLabel) {
//                //System.err.println("lC: |" + className(jcomp) + " | " +
////								   tooltip + " | " +
////								   ((JLabel) jcomp).getText());
//            } else if (jcomp instanceof JTextField) {
////				//System.err.println("lC: |" + className(jcomp) + " | " +
////								   tooltip  + " | " +
////								   ((JTextField) jcomp).getText());
//            } else {
////				//System.err.println("lC: |" + className(jcomp) + " | "
////								   + tooltip);
//            }
//        }
//
//        if (tooltip != null) {
//            if (ht.containsKey(tooltip)) {
//                String newText = "<html>" + (String) ht.get(tooltip) + "</html>";
//                jcomp.setToolTipText(newText);
//            } else {
////				jcomp.setToolTipText(null);
//            }
//        }
//    }
//
//    static void loadToolTips(/*JPanel*/Container topLevel, java.util.Hashtable ht) {
//
//        if (topLevel instanceof JToolBar) {
//            Util.debugPrint(true, "loading toolbar");
//        }
////else Util.debugPrint(true, "not loading toolbar");		
//        if (topLevel instanceof JComponent) {
//            printComponent((JComponent) topLevel, ht);
//        }
//        Component[] components = topLevel.getComponents();
//        if (topLevel instanceof JPopupMenu) {
//            MenuElement[] me = ((JPopupMenu) topLevel).getSubElements();
//            components = new Component[me.length];
//            for (int idx = 0; idx < me.length; idx++) {
//                components[idx] = me[idx].getComponent();
//            }
//        }
//
//        if (topLevel instanceof JMenuItem) {
//            MenuElement[] me = ((JMenuItem) topLevel).getSubElements();
//            components = new Component[me.length];
//            for (int idx = 0; idx < me.length; idx++) {
//                components[idx] = me[idx].getComponent();
//            }
//        }
////		//System.out.println("lC: start " + topLevel.getClass());
//
//        if (topLevel instanceof JTabbedPane) {
//            JTabbedPane jtp = (JTabbedPane) topLevel;
//            int selIdx = jtp.getSelectedIndex();
//            components = new Component[jtp.getTabCount()];
//            for (int idx = 0; idx < components.length; idx++) {
//                jtp.setSelectedIndex(idx);
//                components[idx] = jtp.getSelectedComponent();
//            }
//            jtp.setSelectedIndex(selIdx);
////			components = ((JMenuItem) topLevel).getSubElements();
//        }
//
//        for (int cdx = 0; cdx < components.length; cdx++) {
//            if (components[cdx] instanceof JPanel) {
//                loadToolTips((JPanel) components[cdx], ht);
//            } else if (components[cdx] instanceof JMenuBar) {
//                loadToolTips((JMenuBar) components[cdx], ht);
//            } else if (components[cdx] instanceof JMenuItem) {
//                loadToolTips((JMenuItem) components[cdx], ht);
//            } else if (components[cdx] instanceof JPopupMenu) {
//                loadToolTips((JPopupMenu) components[cdx], ht);
//            } else if (components[cdx] instanceof JToolBar) {
//                loadToolTips((JToolBar) components[cdx], ht);
//            } else if (components[cdx] instanceof JTabbedPane) {
//                loadToolTips((JTabbedPane) components[cdx], ht);
//            } else if (components[cdx] instanceof JScrollPane) {
//                loadToolTips((JScrollPane) components[cdx], ht);
//            } else if (components[cdx] instanceof JViewport) {
//                loadToolTips((JViewport) components[cdx], ht);
//            } else if (components[cdx] instanceof JComponent) {
//                printComponent((JComponent) components[cdx], ht);
//            }
//        }
//    }
    private static final double DegreeInRadians = Math.PI / 180;
    private static final double RadiusOfEarth = 6369.3;

    /*
     * Calculates distance between pairs of coordinations expressed in
     * degrees.  May have problems if both points are not in the same
     * hemisphere.
     */
    public static double polarDistance(double lat1, double lon1, double lat2, double lon2) {
        double sinOriginLat = Math.sin(lat1 * DegreeInRadians);
        double cosOriginLat = Math.cos(lat1 * DegreeInRadians);
        double originLongitude = lon1 * DegreeInRadians;
        double lonRadians = lon2 * DegreeInRadians;
        double latRadians = lat2 * DegreeInRadians;
        double cosD = sinOriginLat * Math.sin(latRadians) + cosOriginLat * Math.cos(latRadians) * Math.cos(originLongitude - lonRadians);
        cosD = Math.acos(cosD);
        double kms = cosD * RadiusOfEarth;
        return kms;
    }

    public static String initialToUpperCase(String inpStr) {
        StringBuffer sb = new StringBuffer(inpStr.toLowerCase().trim());
        sb.replace(0, 1, sb.substring(0, 1).toUpperCase());
        for (int idx = 1; idx < sb.length() - 2; idx++) {
            if (sb.charAt(idx) == ' ') {
                sb.setCharAt(idx + 1, Character.toUpperCase(sb.charAt(idx + 1)));
            }
        }
        return sb.toString();
    }

//    public static void adjustLabelWidth(JComponent jcomp) {
//
//
//        if (jcomp instanceof JLabel) {
//            JLabel jl = (JLabel) jcomp;
//
//        } else if (jcomp instanceof AbstractButton) {
//            AbstractButton ab = (AbstractButton) jcomp;
//            String text = ab.getText();
//            FontMetrics fm = ab.getFontMetrics(ab.getFont());
//            int width = fm.stringWidth(text);
//            Dimension dim = ab.getSize();
////			//System.out.println("lC: |" + className(jcomp) + " | " +
////								   ab.getText() + " " + width + " " + dim.width +
////							  " " + ab.getInsets().right + " " + ab.getInsets().left);
//            if ((width + 25) > dim.width) {
//                dim.width = width + 25;
//                ab.setSize(dim);
//            }
//        } else {
////			//System.out.println("U_aLW: other " + jcomp.getClass());
//        }
//    }
//
//    public static void adjustLabelWidths(Object topLevel) {
//////System.out.println("U_aLW:");
//        if (topLevel instanceof JFrame) {
//            topLevel = ((JFrame) topLevel).getContentPane();
//        }
//        Component[] components = ((Container) topLevel).getComponents();
//
//        if (topLevel instanceof JPopupMenu) {
//            MenuElement[] me = ((JPopupMenu) topLevel).getSubElements();
//            components = new Component[me.length];
//            for (int idx = 0; idx < me.length; idx++) {
//                components[idx] = me[idx].getComponent();
//            }
//        }
//
//        if (topLevel instanceof JMenuItem) {
//            MenuElement[] me = ((JMenuItem) topLevel).getSubElements();
//            components = new Component[me.length];
//            for (int idx = 0; idx < me.length; idx++) {
//                components[idx] = me[idx].getComponent();
//            }
//        }
//
//        if (topLevel instanceof JTabbedPane) {
//            JTabbedPane jtp = (JTabbedPane) topLevel;
//            int selIdx = jtp.getSelectedIndex();
//            components = new Component[jtp.getTabCount()];
//            for (int idx = 0; idx < components.length; idx++) {
//                jtp.setSelectedIndex(idx);
//                components[idx] = jtp.getSelectedComponent();
//            }
//            jtp.setSelectedIndex(selIdx);
//        }
//
//        /*	if (topLevel instanceof com.symantec.itools.javax.swing.JButtonGroupPanel) {
//        java.util.Enumeration abe = ((com.symantec.itools.javax.swing.JButtonGroupPanel) topLevel).getElements();*/
//
//        if (topLevel instanceof javax.swing.ButtonGroup) {
//            java.util.Enumeration abe = ((javax.swing.ButtonGroup) topLevel).getElements();
//            int cnt = 0;
//            for (; abe.hasMoreElements(); abe.nextElement()) {
//                cnt++;
//            }
////			//System.out.println("U_aLW: JButtonGroupPanel " + cnt);
//            components = new Component[cnt];
//            //abe = ((com.symantec.itools.javax.swing.JButtonGroupPanel) topLevel).getElements();
//            abe = ((javax.swing.ButtonGroup) topLevel).getElements();
//            for (int idx = 0; idx < cnt; idx++) {
//                components[idx] = (Component) abe.nextElement();
//            ////System.out.println("U_aLW: buttons " + components[idx].getClass());				
//            }
//        }
//
////		//System.out.println("lC: start " + topLevel.getClass());
//
//        for (int cdx = 0; cdx < components.length; cdx++) {
//            if (components[cdx] instanceof JPanel) {
//                adjustLabelWidths((JPanel) components[cdx]);
//            } else if (components[cdx] instanceof JMenuBar) {
//                adjustLabelWidths((JMenuBar) components[cdx]);
//            } else if (components[cdx] instanceof JMenuItem) {
//                adjustLabelWidths((JMenuItem) components[cdx]);
//            } else if (components[cdx] instanceof JPopupMenu) {
//                adjustLabelWidths((JPopupMenu) components[cdx]);
//            } else if (components[cdx] instanceof JToolBar) {
//                adjustLabelWidths((JToolBar) components[cdx]);
//            } else if (components[cdx] instanceof JTabbedPane) {
//                adjustLabelWidths((JTabbedPane) components[cdx]);
//            } else if (components[cdx] instanceof JScrollPane) {
//                adjustLabelWidths((JScrollPane) components[cdx]);
//            } else if (components[cdx] instanceof JViewport) {
//                adjustLabelWidths((JViewport) components[cdx]);
//            } else if (components[cdx] instanceof JComponent) {
//                adjustLabelWidth((JComponent) components[cdx]);
//            } else if (components[cdx] instanceof AbstractButton) {
//                adjustLabelWidth((AbstractButton) components[cdx]);
//            } else {
//                //System.out.println("U_aLW: " + components[cdx].getClass());
//            }
//        }
//    }
//
    public static void debugPrint(String printLine) {
        LOGGER.fine(printLine);
    }

    public static void debugPrint(boolean flg, String printLine) {
        if (!flg) {
            return;
        }
        try {
            throw new Exception("test");
        } catch (Exception ex) {
            //System.err.println(ex.getStackTrace()[1] + ": " + printLine);
//			//System.out.println("\n\n" + ex.printStackTrace());
        }
    }

    public static String formatDouble(double val, int numdig) {
        if (Double.isNaN(val)) {
//			//System.out.println("U_fD : ");
            return "NaN";
        }
////System.out.println("U_fD: " + val);		
        if (val < 0.001 && val > -0.001 && val != 0.0) {
            String tmp = Double.toString(val);
            int pdx = tmp.indexOf('.');
            int edx = tmp.indexOf('E');
            if (edx == -1) {
                edx = tmp.indexOf('e');
            }
//			//System.out.println("formatDouble: " + tmp + " " + pdx + " " + edx);
            if ((pdx + numdig) >= edx) {
                return tmp;
            }
            return tmp.substring(0, pdx + numdig + 1) + tmp.substring(edx);
        }
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        java.text.FieldPosition fp = new java.text.FieldPosition(NumberFormat.INTEGER_FIELD);
        nf.setMaximumFractionDigits(numdig);
        nf.setMinimumFractionDigits(numdig);
        nf.setGroupingUsed(false);
        return nf.format(val, new StringBuffer(), fp).toString();
    }

//    public static java.io.File makeZipFile(String inpFilNam) {
//        java.io.File inpFil = new File(inpFilNam);
//
//        java.io.File outFil;
//        try{
//            outFil = java.io.File.createTempFile(inpFil.getName(), ".zip");
//        }
//        catch(IOException ioe){
//            //could not create the temp file.
//            outFil = new File(inpFilNam + ".zip");
//        }
//
//        
//        if (outFil.exists()) {
//            outFil.delete();
//        }
//        String filename = inpFil.getName();
//        java.io.FileOutputStream os = null;
//        try {
//            os = new java.io.FileOutputStream(outFil);
//        } catch (FileNotFoundException ex) {
//            java.util.logging.Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
//        }
//        ZipOutputStream zip_os = new ZipOutputStream(os);
//        if (inpFil.isDirectory()) {
//            Util.writeDirToZip(zip_os, inpFil, filename);
//        } else {
//            Util.writeFileToZip(zip_os, inpFil, filename);
//        }
//        try {
//            zip_os.close();
//        } catch (IOException ex) {
//            java.util.logging.Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
//        }
//        return outFil;
//    }
//
//    public static void writeDirToZip(ZipOutputStream zip_os, java.io.File curdirFile, String zipPath, FilenameFilter ff) {
//        java.io.File[] fileList = curdirFile.listFiles(ff);
//        for (int idx = 0; idx < fileList.length; idx++) {
//            if (fileList[idx].isDirectory()) {
//                writeDirToZip(zip_os, new File(fileList[idx]), zipPath + "/" + fileList[idx].getName());
//            } else {
//                writeFileToZip(zip_os, new File(fileList[idx]), zipPath);
//            }
//        }
//    }
//
//    public static void writeDirToZip(ZipOutputStream zip_os, java.io.File curdirFile, String zipPath) {
//        java.io.File[] fileList = curdirFile.listFiles();
//        for (int idx = 0; idx < fileList.length; idx++) {
//            if (fileList[idx].isDirectory()) {
//                writeDirToZip(zip_os, new File(fileList[idx]), zipPath + "/" + fileList[idx].getName());
//            } else {
//                writeFileToZip(zip_os, new File(fileList[idx]), zipPath);
//            }
//        }
//    }
//
    public static void writeFileToZip(ZipOutputStream zip_os, java.io.File inputFile, String zipPath) {
        FileInputStream fis = null;
        try {
            String zipName = zipPath + "/" + inputFile.getName();
            ZipEntry zipEntry = new ZipEntry(zipName);
            fis = new FileInputStream(inputFile);

            byte b[] = new byte[1024];

            zip_os.putNextEntry(zipEntry);
            int len;
            while ((len = fis.read(b)) != -1) {
                zip_os.write(b, 0, len);
            }
            zip_os.closeEntry();            
        } catch (IOException e) {
            LOGGER.severe("IO Error writing zip file \"" + zipPath + "\"" + e.getMessage());
        } catch (Exception e) {
            LOGGER.severe("Error writing zip file \"" + zipPath + "\"" + e.getMessage());
        } finally {
            if (fis != null){
                try {                
                    fis.close();
                } catch (Exception e) {
                    LOGGER.severe("Error closing file stream." + e.getMessage());
                }
            }
        }
    }

    /**
     * Static helper method for getting a unique file name.  The file's extensions are
     * determined by getExtensions().  The append string is ignored.
     * @param file File object representing the file name to increment.
     * @return File object representing the incremented file.
     */
    public static File incrementFileName(File file) {
        return incrementFileName(file, null);
    }

    /**
     * Static helper method for getting a unique file name.  The file's extensions are
     * determined by getExtensions().
     * @param file File object representing the file name to increment.
     * @param append String to append between the file name and extensions.  Ignored if 
     * null.
     * @return File object representing the incremented file.
     */
    public static File incrementFileName(File file, String append) {
        return incrementFileName(file, append, getExtensions(file.getName()));
    }

    /**
     * Static method for getting a unique file name.  The method accepts a String to
     * append, such as "_backup" which will be placed between the file name and passed
     * extensions.  If the file already exists, the method will look for an integer
     * at the end of the file name and increment by 1.  If there is no integer in the 
     * file name the method will append and integer in the format "_#" so that # is a 
     * unique number.
     * @param file File object representing the file name to increment.
     * @param append String to append between the file name and extensions.  Ignored if 
     * null.
     * @param extensions String[] of extensions.
     * @return File object representing the incremented file.
     */
    public static File incrementFileName(File file, String append, String... extensions) {
        String fileName = file.getName();

        //remove the extensions from the filename
        if (extensions != null) {
            fileName = purgeExtensions(fileName, extensions);
        }

        //add the append string.
        if (append != null) {
            fileName += append;
        }

        //Do we need to increment the numbers?
        File tempFile = new File(file.getParentFile(), addExtensions(fileName, extensions));
        //Put the extensions back on

        if (tempFile.exists() == false) {
            //file is unique, return it without regard to a number
            return tempFile;
        } else {
            //We need to add numbers so we'll discard this file for now.
            tempFile = null;
        }


        int number;
        String prefix;
        //Find the last underscore
        int underscoreIndex = fileName.lastIndexOf("_");
        if (underscoreIndex > 1) {
            //We have an underscore
            prefix = fileName.substring(0, underscoreIndex + 1);
            try {
                String numberString = fileName.substring(underscoreIndex + 1);
                number = Integer.parseInt(numberString);
            } catch (Exception e) {
                //The characters after the underscore are not an integer.
                number = 1;
                prefix = fileName + "_";
            }
        } else {
            //No underscore
            number = 1;
            prefix = fileName + "_";
        }

        fileName = prefix + Integer.toString(number);

        tempFile = new File(file.getParentFile(), addExtensions(fileName, extensions));
        while (tempFile.exists()) {
            fileName = prefix + Integer.toString(number);
            tempFile = new File(file.getParentFile(), addExtensions(fileName, extensions));
            number++;
        }
        return tempFile;
    }

    /**
     * Appends each extension in order to the path.
     * @param path Path to append extensions to.
     * @param extensions String[] of extensions to append.
     * @return Appended path.
     */
    public static String addExtensions(String path, String... extensions) {
        if (extensions != null) {
            for (String extension : extensions) {
                path = path.concat(extension);
            }
        }
        return path;
    }

    /**
     * Removes the passed extensions from the string.
     * @param path String to remove extensions from.
     * @param extensions String[] of extensions with the periods at the start of 
     * each extension.
     * @return Purged String.
     */
    public static String purgeExtensions(String path, String... extensions) {
        String newPath = path;
        boolean extensionRemaining = true;

        while (extensionRemaining) {
            for (String extension : extensions) {
                if (newPath.endsWith(extension)) {
                    int end = newPath.lastIndexOf(extension);
                    newPath = newPath.substring(0, end);
                }
            }
            //Check if an extension is remaining.
            extensionRemaining = false;
            for (String extension : extensions) {
                if (newPath.endsWith(extension)) {
                    extensionRemaining = true;
                    break;
                }
            }
        }
        return newPath;
    }

    /**
     * Returns an array of strings of the extensions of the file name.  The periods
     * are included at the start of each extension.
     * @param path String to find the extensions in.
     * @return Array of Strings of the extensions.
     */
    public static String[] getExtensions(String path) {
        Pattern pattern = Pattern.compile("\\.[\\S&&[^\\.]]++");
        Matcher matcher = pattern.matcher(path);
        Vector<String> matches = new Vector<String>();
        while (matcher.find()) {
            int start = matcher.start();
            int end = matcher.end();
            String match = path.substring(start, end);
            if (match.length() < 5){
                matches.add(match);
            }
            
        }

        String[] result = new String[matches.size()];
        for (int i = 0; i < matches.size(); i++) {
            result[i] = matches.get(i);
        }
        return result;
    }
    private static Pattern c_parsingPattern;

    private synchronized static Pattern getParsingPattern() {
        if (c_parsingPattern == null) {
            c_parsingPattern = Pattern.compile("(\\$\\{(.*?)\\})");
        }
        return c_parsingPattern;
    }

    public static String parse(String text) {
        return parse(text, null);
    }

    public static String parse(String text, Map<String, String> props) {
        if (text == null) {
            return null;
        }
        Matcher matcher = getParsingPattern().matcher(text);
        StringBuffer buffer = new StringBuffer();
        while (matcher.find()) {
            String property = matcher.group(2);
            String replacement = null;
            if (props != null && props.containsKey(property)) {
                //user can specify more props
                replacement = props.get(property);
//            } else {
//                replacement = getProperty(property);
            }

            if (replacement != null) {
                //handle the regex quirks with slashes and question marks
                replacement = replacement.replace("\\", "\\\\");
                replacement = replacement.replace("$", "\\$");
                matcher.appendReplacement(buffer, replacement);
            }
        }
        matcher.appendTail(buffer);

        return buffer.toString();
    }

//    public static String getProperty(String property) {
//        //user directories
//        if ("user.home".equals(property)) {
//            return About.getUserHome().getAbsolutePath();
//        } else if ("user.documents".equals(property)) {
//            return About.getUserDocuments().getAbsolutePath();
//        } else if ("user.weps".equals(property)) {
//            return About.getUserWeps().getAbsolutePath();
//        } else if ("user.working".equals(property)) {
//            return About.getUserWorking().getAbsolutePath();
//        } //project
//        else if ("project.directory".equals(property)) {
//            String path = ConfigData.getDefault().getDataParsed(ConfigData.CurrentProj);
//            path = pad(path);
//            return path;
//        } //windgen
//        else if ("windgen.data".equals(property)) {
//            String data = ConfigData.getDefault().getDataParsed(ConfigData.WinData);
//            data = pad(data);
//            return data;
//        } //cligen
//        else if ("cligen.data".equals(property)) {
//            String data = ConfigData.getDefault().getDataParsed(ConfigData.CliData);
//            data = pad(data);
//            return data;
//
//        }
//        else if("weps.databases".equals(property)){
//            File file = About.getWepsDatabases();
//            return file != null ? file.getAbsolutePath() : null;
//        }
//
//
//        //deprecated properties
//        else if ("USER_HOME_DIR".equals(property)) {
//            LOGGER.warning("${USER_HOME_DIR} is deprecated.  Use ${user.documents} instead.");
//            return getProperty("user.documents");
//        } else if ("WINDGEN_DB".equals(property)) {
//            LOGGER.warning("${WINDGEN_DB} is deprecated.  Use ${windgen.data} instead.");
//            return getProperty("windgen.data");
//        } else if ("CLIGEN_DB".equals(property)) {
//            LOGGER.warning("${CLIGEN_DB} is deprecated.  Use ${cligen.data} instead.");
//            return getProperty("cligen.data");
//        } else if ("PROJECT_DIRECTORY".equals(property)) {
//            LOGGER.warning("${PROJECT_DIRECTORY} is deprecated.  Use ${project.directory} instead.");
//            return getProperty("project.directory");
//        } //system properties 
//        else if (System.getProperties().containsKey(property)) {
//            return System.getProperty(property);
//        }
//        else if (System.getenv().containsKey(property)){
//            return System.getenv(property);
//        }
//
//
//        //nothing, return null
//        LOGGER.error("Unable to parse property: " + property);
//        return null;
//    }
//
    private static String pad(String string) {
        if (string == null) {
            return "";
        } else {
            return string;
        }
    }
    
    public static String encrypt(String input, String key){
        return encodeSafeXml(xorCipher(input, key));              
    }
    
    public static String decrypt(String input, String key){
        return xorCipher(decodeSafeXml(input), key);
    }
       
    public static String xorCipher(String input, String key){
        if (input == null || key == null){
            return null;
        }
        
        byte[] inputBytes = input.getBytes();
        byte[] keyBytes = key.getBytes();                
        
        int k = 0;
        
        //loop over each input byte
        for (int i = 0; i < inputBytes.length; i++){
            inputBytes[i] = (byte)(inputBytes[i] ^ keyBytes[k]);
            
            //step over the key
            if (k < keyBytes.length - 1){
                k++;
            }
            else{
                k = 0;
            }
        }
        
        return new String(inputBytes);
        
    }
    
    private static final String HEXCHARS[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
    
    public static String encodeSafeXml(String input){
        if (input == null){
            return null;
        }
        byte[] inputBytes = input.getBytes();

        StringBuffer output = new StringBuffer(input.length() * 2);
        byte ch = 0x00;
        for (int i = 0; i < inputBytes.length; i++){
            ch = (byte) (inputBytes[i] & 0xF0); //strip off high bit
            ch = (byte) (ch >>> 4); //shift bits down
            ch = (byte)(ch & 0x0F); //prepare high bit
            
            output.append(HEXCHARS[(int)ch]);
            
            ch = (byte) (inputBytes[i] & 0x0F); //strip off low bit
            output.append(HEXCHARS[(int)ch]);
        }
        
        return output.toString();
    }
    
    public static String decodeSafeXml(String input){
        if (input == null){
            return null;
        }
        try{
            byte[] b = new byte[1];
            StringBuffer output = new StringBuffer();
            for (int i = 0; i < input.length(); i=i+2){
                String sub = input.substring(i, i+2);
                b[0] = Byte.parseByte(sub, 16);
                output.append(new String(b));
            }
            return output.toString();
            }
        catch(NumberFormatException nfe){
            LOGGER.warning("Unable to decode string: " + input);
            return null;
        }
    }

    public static void logMemoryUsage(){
        final double bytesToMegabytes = 9.5367431640625e-07;
        double totalMem = Runtime.getRuntime().totalMemory() * bytesToMegabytes;
        double maxMem = Runtime.getRuntime().maxMemory()* bytesToMegabytes;
        double freeMem = Runtime.getRuntime().freeMemory() * bytesToMegabytes;
        double usedMem = totalMem - freeMem;
        
        LOGGER.fine(String.format("Memory Usage: %1$f.2MB used, %2$f.2MB free %3$f.2MB max", usedMem, totalMem, maxMem));
    }



    public static String makePrettyTable (String[]... rows){                
        //check that the rows all have the same number of columns
        int columnCount = -1;
        for (String[] row : rows){
            if (columnCount == -1){
                columnCount = row.length;
            }
            else if (row.length != columnCount){
                throw new IllegalArgumentException("Table rows do not all have the same number of columns");
            }
        }

        //calculate the column widths
        int[] columnWidths = new int[columnCount];
        //loop over each column
        for (int i = 0; i < columnCount; i++){
            //loop over each row
            for (String[] row : rows){
                //calculate the maximum value length for the column for each row
                columnWidths[i] = Math.max(columnWidths[i], row[i] != null ? row[i].trim().length() : 0);
            }//end row loop
        }//end column loop

        //Create the buffer for the table
        StringBuffer table = new StringBuffer();

        //column delimiter
        String delimiter = " | ";

        //append each row with padding
        for(String[] row : rows){
            for (int i = 0; i < columnCount ; i++){
                if(i > 0){
                    //not the first column, add the delimiter
                    table.append(delimiter);
                }

                //append the value
                String value = row[i] != null ? row[i].trim() : "";
                table.append(value);

                //only pad if not the last column
                if (i != columnCount - 1){
                    int padding = columnWidths[i] - value.length();
                    for (int p = 0; p < padding; p++){
                        table.append(" ");
                    }
                }
            }
            //append new line
            table.append("\n");
        }


        return table.toString();
    }

//    public static <C extends Component> C findFirstDecendent(Component comp, Class <C> c){
//        return findDecendent(comp, c, null);
//    }
//
//    public static <C extends Component> C findDecendent(Component comp, Class <C> c, FindMatcher<C> matcher){
//        if(c.isInstance(comp)){
//            if(matcher != null){
//                return matcher.matches((C)comp) ? (C) comp : null;
//            }
//            else{
//                return (C) comp;
//            }
//        }
//        else if(comp instanceof Container){
//            Container box = (Container) comp;
//            Component[] children = box.getComponents();
//            for(Component child : children){
//                C result = findFirstDecendent(child, c);
//                if(result != null){
//                    return result;
//                }
//            }
//        }
//        return null;
//    }
//
    public static interface FindMatcher <O>{
        public boolean matches(O o);
    }

    public static boolean isWindows(){
        return System.getProperty("os.name").toLowerCase().contains("win");

    }
    
    public static boolean is64Bit(){
        return "64".equals(System.getProperty("sun.arch.data.model"));
    }
    
    

//    public static File[] findFiles(File root, FileFilter filter, boolean recursive, int limit){
//        List<File> results = new LinkedList<File>();
//
//        findFiles(results, root, filter, true, recursive, limit);
//
//        return results.toArray(new File[results.size()]);
//    }
//
//    private static void findFiles(List<File> results, File file, FileFilter filter, boolean root, boolean recursive, int limit){
//
//        boolean accept = filter.accept(file);
//
//        if(accept){
//            results.add(file);
//
//            //if we have a limit here.
//            if(limit > 0 && results.size() == limit){
//                return;
//            }
//        }
//
//
//        if(file.isDirectory() && (root || recursive)){
//            File[] children = file.listFiles(file.getArchiveDetector());
//
//            if(children != null){
//                for (File child : children){
//                    findFiles(results, child, filter, false, recursive, limit);
//
//                    if(limit > 0 && results.size() == limit){
//                        return;
//                    }
//                }
//            }
//
//        }
//    }
//
    public static String fileContents(String path){
        return fileContents(new File(path));
    }

    public static String fileContents(File file){
        StringBuilder contents = new StringBuilder();
        BufferedReader reader = null;
        try{
            reader = new BufferedReader(new FileReader(file));
            for(String line = reader.readLine(); line != null; line = reader.readLine()){
                contents.append(line);
                contents.append("\n");
            }
        }
        catch(Exception e){
            LOGGER.warning("Unable to read file contents: " + file.getAbsolutePath() + "\n" + e.getMessage());
        }
        finally{
            if(reader != null){
                try{
                    reader.close();
                }
                catch(Exception e){
                    LOGGER.warning("Unable to close file: " + file.getAbsolutePath() + "\n" + e.getMessage());
                }

            }
        }
        return contents.toString();
    }
    
    
    public static boolean isValidEmail(String email){
        if(email == null || email.trim().isEmpty()){
            return false;
        }
        
        //regex for emails        
        String regex = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";                
        
        return Pattern.matches(regex, email.trim());        
        
        
        
    }
    
    /**
     * Parses the first decimal component of a version string. 
     * @param version String to parse
     * @return the float value of the first decimal component in the string or -1
     */
    public static float parseVersionStringToFloat(String version) {
        Pattern pattern = Pattern.compile("([0-9]+(\\.[0-9]+)?)");

        Matcher matcher = pattern.matcher(version);
        
        if(matcher.find()){
            String floatPart = matcher.group();
            try{
                return Float.parseFloat(floatPart);
            }
            catch(NumberFormatException nfe){
//                Logger.getLogger(About.class).error("Unable to parse version string: " + version, nfe);
                return -1;
            }
        }
        else{
            return -1;
        }        
    }
}