// 
// The Waveset SPML General License 
// 
// Version 0.1, April 2003
// Copyright (C) 2003 Waveset Technologies, Inc..
// 6034 West Courtyard Drive, Suite 210, Austin, Texas 78730
// All rights reserved.
// 
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// 
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions, and the disclaimers in Sections 6
//    and 7 below.
// 
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the disclaimers in Sections 6
//    and 7 below in the documentation and/or other materials provided
//    with the distribution.
// 
// 3. The end-user documentation included with the redistribution, if
//    any, must include the following acknowledgment:
// 
//    "This product includes software developed by 
//     Waveset Technologies, Inc. (www.waveset.com)."
// 
//    Alternately, this acknowledgment may appear in the software itself, if
//    and wherever such third-party acknowledgments normally appear.
//  
// 4. The names "Waveset" and "Waveset Technologies, Inc." must not be
//    used to endorse or promote products derived from this software
//    without the prior written permission of Waveset. For written
//    permission, please contact www.waveset.com.
//  
// 5. Products derived from this software may not be called "Waveset",
//    nor may "Waveset" appear in their name, without the prior written
//    permission of Waveset.
//  
// 6. NO WARRANTY 
// 
//    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED
//    OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//    DISCLAIMED.
// 
// 7.  LIMITATION OF LIABILITY
// 
//    IN NO EVENT SHALL THE WAVESET OR ITS LICENSORS BE LIABLE FOR ANY
//    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
//    GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
//    IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
//    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 
// End of Terms and Conditions
// ====================================================================
//
// Component Name: org.openspml.util.Util
//
// Author(s): Jeff Larson
//
// Description:
//
// Miscellenaous utilities.
//
//

package org.openspml.util;

import java.util.*;
import java.io.*;

public class Util {

    //////////////////////////////////////////////////////////////////////
    //
    // File IO
    //
    //////////////////////////////////////////////////////////////////////

    /**
     * Store the contents of a String in a file.
     */
    static public void writeFile(String name, String contents)
	throws java.io.IOException {

	String path = findOutputFile(name);
	FileOutputStream fos = null;
	try {
	    fos = new FileOutputStream(path);
	    fos.write(contents.getBytes());
	}
	finally {
	    try {
		if (fos != null) fos.close();
	    }
	    catch (java.io.IOException e) {
		// ignore
	    }
	}
    }

    /**
     * Store the contents of a String in a file, ignoring exceptions.
     */
    static public void writeFileQuietly(String name, String contents) {

        try {
            writeFile(name, contents);
        }
        catch (Throwable t) {
        }
    }

    /**
     * Build an absolute path name for a file.
     * Typically used when you want to write an output file to
     * the "current working directory".
     *
     * If the name is already an absolute path we use it, otherwise
     * we use the system property "user.dir" as the root directory
     * and add the name.
     */
    public static String findOutputFile(String name) {

	String path = null;

	if (name.charAt(0) == '/' || name.indexOf(":") != -1) {

	    // its an absolute path, just return it
	    path = name;
	}
	else {
	    // try relative to user.dir
	    String root = System.getProperty("user.dir");
	    if (root != null)
		path = root + "/" + name;
	    else {
		// no obvious way to position it, have to leave
		// it in the process' current working directory
		path = name;
	    }
	}

	return path;
    }

    /**
     * Read the contents of a file and return it as a String.
     */
    static public byte[] readFileBytes(File file)
	throws java.io.IOException {

	byte[] bytes = null;
	FileInputStream fis = new FileInputStream(file);
	try {
	    ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
	    byte[] buf = new byte[1024];
	    int bytesRead = 0;
	    while ((bytesRead = fis.read(buf)) != -1) {
		bout.write(buf, 0, bytesRead);
	    }
	    bytes = bout.toByteArray();
	}
	finally {
	    try {
		fis.close();
	    }
	    catch (java.io.IOException ex) {
		// ignore these
	    }
        }
        return bytes;
    }

    /**
     * Read the contents of a file and return it as a String.
     */
    static public String readFile(String name)
	throws java.io.IOException {

	File f = new File(findFile(name));
	byte[] bytes = readFileBytes(f);
	return new String(bytes);
    }

    /**
     * @return <code>true</code> if the specified path
     * appears to be an <em>absolute</em> path; otherwise <code>false</code>.
     * <p>
     * Don't bother to call this if you already have
     * (or plan to construct) a <code>File</code> with the specified path.
     * This method is a poor man's {@link java.io.File#isAbsolute()},
     * this method's advantage is that it avoids object construction.
     */
    public static boolean isAbsolutePath(String path) {
	//
	// If the first character is a slash,
	// then the path is an Unix-style absolute path.
	//
	// If the second character is a colon
	// (delimiting the drive letter),
	// then the path is a Windows-style absolute path.
	//
	return (path != null &&
		((path.length() > 0 && 
		  (path.charAt(0) == File.separatorChar ||	
		   path.charAt(0) == '.')) ||
		 (path.length() > 1 && path.charAt(1) == ':')));
    }

    public static String findFile(String property, String name) {

	String path = null;

	if (isAbsolutePath(name)) {
	    // it's an absolute path, just return it
	    path = name;
	}
	else {
	    // First try relative to the property
	    if (property != null) {
		String root = System.getProperty(property);
		if (root != null) {
		    String testpath = root + File.separator + name;
		    File f = new File(testpath);
		    if (f.isFile())
			path = testpath;
		}
	    }

	    if (path == null) {
		// if we still couldn't find anything,
		// just use the original name, and assume
		// its in the process current working directory
		path = name;
	    }
	}

	return path;
    }

    public static String findFile(String name) {

        return findFile("user.dir", name);
    }

    //////////////////////////////////////////////////////////////////////
    //
    // String/List conversion
    //
    //////////////////////////////////////////////////////////////////////

    static public List decodeCommaString(String src) {
	return decodeCommaString(src, false);
    }

    static public List decodeCommaString(String src, boolean filterEmpty) {

	List list = null;
	if (src != null) {
	    StringTokenizer st = new StringTokenizer(src, ",");
	    while (st.hasMoreElements()) {
		if (list == null)
		    list = new ArrayList();
		// Trim the token to remove leading space,
		// important since encodeCommansString leaves
		// a space after the comma.
		// Hmm, should we not be putting the spaces here?
		// It does improve readability though...
		String tok = st.nextToken().trim();
		if (!filterEmpty || tok.length() > 0)
		    list.add(tok);
	    }
	}

	return list;
    }

    /**
     * Convert a list of strings into a comma delimited list.
     */
    static public String encodeCommaString(List list) {
	return encodeCommaString(list, false);
    }

    static public String encodeCommaString(List list, boolean filterEmpty) {

	String commaString = null;

	if (list != null) {
	    StringBuffer b = new StringBuffer();
	    int added = 0;
	    for (int i = 0 ; i < list.size() ; i++) {
		String s = (String)list.get(i);
		if (!filterEmpty || (s != null && s.length() > 0)) {
		    if (added > 0)
			b.append(", ");
		    b.append(s);
		    added++;
		}
	    }
	    commaString = b.toString();
	}
	return commaString;
    }

    /**
     * Given a newline deliminted string, break it up into
     * a List of Strings.
     */
    public static List decodeNewlineString(String data, boolean filterEmpty) {

        List list = null;
	if (data != null) {
	    StringTokenizer tokens = new StringTokenizer(data,"\n\r");
	    if (tokens.countTokens() > 0) {
		list = new ArrayList();
		while (tokens.hasMoreTokens()) {
		    String s = tokens.nextToken();
		    s = s.trim();
		    if (s.length() > 0 || !filterEmpty)
			list.add(s);
		}
	    }
	}
	return list;
    }

}
