    // formatting Date()
import java.text.SimpleDateFormat;
import java.util.Date;

    // calculation CRC32 from byte array
import java.util.zip.CRC32;
import java.util.zip.Checksum;

import java.util.Arrays;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;

public class TestDTFormat
{

    /** Controls whether the generated file name should be led in with the
     *  extended class' simple name, defaults to <code>true</code>. */
    static public boolean bFileNameWithSimpleName=true;    // create with leading simple name of the class that gets extended


        // simple Date formatter
    /** Defines the format pattern (<code>"yyyyMMdd_HHmmss_SSS"</code>) that
     *  {@link #formatDateTime()} and {@link #formatDateTime(Date d)} use; this
     *  one is for showing date and time.
     */
    static SimpleDateFormat sdf_dt=new SimpleDateFormat("yyyyMMdd_HHmmss_SSS");

    /** Defines the format pattern (<code>"yyyyMMdd"</code>) that
     *  {@link #formatDateTime()} and {@link #formatDateTime(Date d)} use; this
     *  one is for showing date only.
     */
    static SimpleDateFormat sdf_d =new SimpleDateFormat("yyyyMMdd");

    /** Controls whether the generated file name includes a date and time
     *  portion, defaults to <code>true</code>. */
    static public boolean bFileNameWithDateTime  =true;    // create date time portion for file name

    /** Controls whether the generated file name's date and time portion
     *  should contain the date portion only, defaults to <code>false</code>. */
    static public boolean bFileNameWithDateOnly  =false;    // create date portion for file name


    // save generated program to file section -->
    /** Flag that determines whether the generated program should be stored in the file system. */
    static public boolean bSaveToFilesystem=false;          // do not save to file system

    /** Path where a generated program should be stored to, defaults to the Java temporary directory
     *  <code>(System.getProperty("java.io.tmpdir"))</code>. */
    static public  String pathToSaveTo  =System.getProperty("java.io.tmpdir");   // use Java's tmp dirctory by default

    /** Stores the current platform's file separator character. */
    static private String fileSeparator=System.getProperty("file.separator");   // platform's file separator

    public static void main (String args[])
    {
        Date             dt =new Date();
        System.out.println("dt=["+dt+"], fmtDate: ["+formatDateTime(dt)+"]");
        System.out.println("dt=["+new Date()+"], fmtDate: ["+formatDateTime()+"]");

        String test="Tirol isch lei oans, isch a Landl a kloans, isch a ...";
        System.out.println("test=["+test+"], crc32=["+calcCRC32(test)+"]");
        System.out.println("---");

        String res=null;
        String [] meth_01=new String[]{"hi"};
        String [] meth_02=new String[]{"hi","there"};
        Class  [] clz_01 =new Class [] {java.awt.event.ActionListener.class};
        Class  [] clz_02 =new Class [] {java.awt.event.ActionListener.class,
                                        javax.swing.event.MouseInputListener.class};

        res=createFileName(java.lang.Long.class , null, null, null);
        res=createFileName(java.lang.Long.class , "newRgfName", null, null);
        res=createFileName(java.lang.Long.class , null, meth_01, null);
        res=createFileName(java.lang.Long.class , null, meth_02, null);
        res=createFileName(java.lang.Long.class , null, null, clz_01);
        res=createFileName(java.lang.Long.class , null, null, clz_02);
        res=createFileName(java.lang.Long.class , "newRgfName", meth_02, clz_02);

        System.out.println("\ntesting creating files...");
        System.out.println("A1) pathToSaveTo=["+pathToSaveTo+"], bSaveToFilesystem=["+bSaveToFilesystem+"]");
        pathToSaveTo=System.getProperty("user.dir");
        bSaveToFilesystem=true;
        System.out.println("A2) pathToSaveTo=["+pathToSaveTo+"], bSaveToFilesystem=["+bSaveToFilesystem+"]");

        testCreateFile(createFileName(java.lang.Long.class , null, null, null) );
        testCreateFile(createFileName(java.lang.Long.class , "newRgfName", null, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, meth_01, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, meth_02, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, null, clz_01) );
        testCreateFile(createFileName(java.lang.Long.class , null, null, clz_02) );
        testCreateFile(createFileName(java.lang.Long.class , "newRgfName", meth_02, clz_02) );

        testCreateFile(createFileName(java.lang.Long.class , null, null, null) );
        testCreateFile(createFileName(java.lang.Long.class , "newRgfName", null, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, meth_01, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, meth_02, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, null, clz_01) );
        testCreateFile(createFileName(java.lang.Long.class , null, null, clz_02) );
        testCreateFile(createFileName(java.lang.Long.class , "newRgfName", meth_02, clz_02) );


        System.out.println("\ntesting creating files, now inhibiting ...");
        bSaveToFilesystem=false;
        System.out.println("A3) pathToSaveTo=["+pathToSaveTo+"], bSaveToFilesystem=["+bSaveToFilesystem+"]");

        testCreateFile(createFileName(java.lang.Long.class , null, null, null) );
        testCreateFile(createFileName(java.lang.Long.class , "newRgfName", null, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, meth_01, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, meth_02, null) );
        testCreateFile(createFileName(java.lang.Long.class , null, null, clz_01) );
        testCreateFile(createFileName(java.lang.Long.class , null, null, clz_02) );
        testCreateFile(createFileName(java.lang.Long.class , "newRgfName", meth_02, clz_02) );

    }

    static boolean testCreateFile(String fileName)
    {
        if (bSaveToFilesystem==false)
        {
            return false;       // indicate no file created
        }

        FileOutputStream outFile=null;

        try
        {
            outFile=new FileOutputStream(pathToSaveTo+fileSeparator+fileName);
            outFile.write("abc".getBytes());
            outFile.close();
        }
        catch (Exception exc)
        {
            System.err.println("*** ERROR *** ["+exc.toString()+"]");
            return false;       // indicate no file created
        }
        return true;
    }



    /** Creates and formats a {@link Date} object. Depending on {@link #bFileNameWithDateOnly}
     *  the time portion may be left out.
     *
     * @return formatted {@link Date} object representing the date and time of invocation
     */
    public static String formatDateTime()
    {
        if (bFileNameWithDateOnly)       // use Date and Time portion
        {
            return sdf_d.format(new Date());
        }
        return sdf_dt.format(new Date());    // use Date portion only
    }

    /** Formats a {@link Date} object.  Depending on {@link #bFileNameWithDateOnly}
     *  the time portion may be left out.
     *
     * @param d the {@link Date} object to format
     * @return formatted {@link Date} object representing
     */
    public static String formatDateTime(Date d)
    {
        if (bFileNameWithDateOnly)       // use Date and Time portion
        {
            return sdf_d.format(d);
        }
        return sdf_dt.format(d);    // use Date portion only
    }

    /** Calculate the CRC32 value for the supplied string and return an uppercased hex-string.
     *
     * @param str the String for which the checksum should get calculated
     * @return the uppercased hexadecimal value
     */
    public static String calcCRC32(String str)
    {
        if (str==null)      // return null, if no String
        {
            return null;
        }
        byte [] barrData=str.getBytes();            // get byte array
        Checksum cs=new CRC32();                    // get CRC32 Checksum object
        cs.update(barrData, 0, barrData.length);    // calc CRC32
        return Long.toHexString(cs.getValue()).toUpperCase();
    }

/** This method will create a file name that by default gets built in the following
 *  form: <code>SimpleClassName_ClassName_$RexxExtendClass$_CRC32_DATE_TIME_MSEC.java</code>.
 *  The generation of the file name is controlled by {@link #bFileNameWithSimpleName},
 *  {@link #bFileNameWithDateTime} and {@link #bFileNameWithDateOnly}.
 *
 *  @param clzToProxy the class object that gets extended
 *  @param newClzName optional, the class name for the extended class
 *  @param methodNames2proxy optional, an array of method names to proxy
 *  @param interfaceClasses optional, an array of Interface classes whose abstract methods to proxy
 *
 *  @return the file name that should be used for storing the generated proxy class
 */
static    String createFileName(final Class    clzToProxy,
                          final String   newClzName,
                          final String[] methodNames2proxy,
                          final Class[]  interfaceClasses
                          )
    {
        String strClzSimpleName     =clzToProxy.getSimpleName();
        String strClzName           =clzToProxy.getName();
        String strMethodNames2proxy =Arrays.toString(methodNames2proxy);
        String strInterfaceClasses  =Arrays.toString(interfaceClasses );

            // String that gets used for calculating CRC32; this way the CRC32 will
            // indicate that generated classes may have identical content
        String strToCalcCRC32=strClzName+"-"+newClzName+"-"+strMethodNames2proxy+"-"+strInterfaceClasses;
        String strCRC32=calcCRC32(strToCalcCRC32);

        StringBuffer sb=new StringBuffer();

        if (bFileNameWithSimpleName)    // lead in with simple class name?
        {
            sb.append(strClzSimpleName).append("_");
        }

        sb.append(strClzName).append("_$RexxExtendClass$_").append(strCRC32);

        if (bFileNameWithDateTime)      // include date/time?
        {
            sb.append("_").append(formatDateTime());
        }
        sb.append(".java");             // append file type

        // String tmpFileName=strClzSimpleName+"_"+strClzName+"_$RexxExtendClass$_"+strCRC32+"_"+formatDateTime()+".java";

        String tmpFileName=sb.toString();

System.out.println("strToCalcCRC32=["+strToCalcCRC32+"]");
System.out.println("\ttmpFileName=["+tmpFileName+"]\n");

       return tmpFileName;
    }


}


