com.flexoodb.common.FlexUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.flexoodb.common.FlexUtils.java

Source

/*
 * FlexUtils.java
 *
 * Created on Mar 17, 2009 11:17:41 AM
 *
 * Copyright (C) 2009 Jayson Yu
 *
 * 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 2 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,
 * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

package com.flexoodb.common;

import com.flexoodb.FlexContainer;
import com.flexoodb.modeler.Config;
import com.flexoodb.modeler.ConfigElement;
import com.flexoodb.modeler.ConfigFieldInfo;
import com.flexoodb.modeler.FlexAttribute;
import com.flexoodb.modeler.FlexElement;
import com.flexoodb.pool.RecordSet;
import com.intigrix.front.FileContainer;
import com.intigrix.node.ResultPacket;
import com.sun.mail.smtp.SMTPTransport;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.Security;
import java.sql.Blob;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.Formatter;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.imageio.ImageIO;
import javax.mail.BodyPart;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.XMLConfiguration;

/**
 * utility class for the flexoodb API.
 * 
 * @author      Jayson Yu
 * @version     %I%, %G%
 * @since       1.0
 */
public class FlexUtils {

    public static String _indexabletypes = "boolean,BigInteger,BigDecimal,Boolean,base64Binary,Date,DateTime,Double,Float,Integer,Long,Short,String,XMLGregorianCalendar,byte[]";
    public static String _textfields = "config,configuration,background,commentary,commentaries,comments,comment,description,descriptions,detail,details,info,information,introduction,note,notes,objective,objectives,observation,observations,remark,remarks,summary,update,updates";
    public static String _types = "base64binary,date,datetime,float,double,text,textarea,string,integer,decimal,select,file,boolean";
    public static String[] _binarytypes = new String[] { "byte[]", "Serializable" };
    public static String _dateformat = "yyyy-MM-dd HH:mm:ss";

    /**
    * checks if the passed object has (at a minimum) a setId() and getId() methods.
    *
    * @param  obj the object to check for setId() and getId() methods.
    * @return whether the passed object has id methods.
    */
    static public boolean hasIdMethods(Object obj) throws Exception {
        boolean setok = false, getok = false;

        Class c = null;

        if (obj instanceof Class) {
            c = (Class) obj;
        } else {
            c = obj.getClass();
        }

        Method[] m = c.getMethods();

        for (int i = 0; i < m.length; i++) {
            String name = m[i].getName();
            String retval = m[i].getReturnType().getSimpleName();
            if (retval.equalsIgnoreCase("void") && name.startsWith("setId")) {
                setok = true;
            }
            if (retval.indexOf("String") > -1 && name.startsWith("getId")) {
                getok = true;
            }

            if (getok && setok) {
                break;
            }
        }

        return (setok && getok);
    }

    /**
    * sets the Id of a given object using the passed id.
    * 
    * @param  id the id that will be used to update the object.
    * @param  obj the object whose Id will be updated.
    */
    static public void setId(String id, Object obj) throws Exception {
        Class c = obj.getClass();
        Class[] p = new Class[1];
        p[0] = String.class;
        Method met = c.getMethod("setId", p);
        Object o = null;
        try {
            Object[] o1 = new Object[1];
            o1[0] = id;
            met.invoke(obj, o1);
        } catch (Exception g) {
            throw g;
        }
    }

    /**
    * retrieves the id of a given persistence object.
    * 
    * @param  obj the object whose id will be obtained.
    * @return the id of the object.
    */
    static public String getId(Object obj) throws Exception {
        String id = null;
        Class c = obj.getClass();
        Method[] m = c.getMethods();

        for (int i = 0; i < m.length; i++) {
            String name = m[i].getName();
            String retval = m[i].getReturnType().getSimpleName();
            if (retval.endsWith("String") && name.startsWith("getId")) {
                Method met = c.getMethod("getId", (Class[]) null);
                Object o = null;
                try {
                    o = met.invoke(obj, (Object[]) null);
                    id = (String) o;
                } catch (Exception g) {
                }
                break;
            }
        }
        return id;
    }

    /**
    * gets all methods with a prefix "set" (e.g. setName()) and returns this as a Hashtable with the input type as the values.
    *
    * @param  obj the object to retrieve the methods from.
    * @return a hashtable of the methods with the "set" prefix and the type as values.
    */
    /*static public Hashtable getSetMethods(Object obj) throws Exception
    {
        
    Hashtable<String,String> methods = new Hashtable<String,String>();
        
    Class c = null;
        
    if (obj instanceof Class)
    {
        c = (Class) obj;
    }
    else
    {
        c = obj.getClass();
    }
        
    Method[] m = c.getMethods();
        
    for (int i=0;i<m.length;i++)
    {
        String name = m[i].getName();
        Class[] params = m[i].getParameterTypes();
        if (params!=null && params.length > 0)
        {
            String paramtype = params[0].getSimpleName();
            if (paramtype!=null && name.startsWith("set") && !name.equals("setId"))
            {
                methods.put(name,paramtype);
            }
        }
    }
        
    return methods;
    }
    */

    /**
    * gets the packagename of a given object.
    *
    * @param  obj the object to retrieve the package name from.
    * @return the packagename.
    */
    static public String getPackageName(Object obj) throws Exception {
        Class c = null;
        if (obj instanceof Class) {
            c = (Class) obj;
        } else {
            c = obj.getClass();
        }
        return c.getPackage().getName();
    }

    /**
    * retrieves all possible elements (using all getXXX--where XXX is any method name) of an object.
    * 
    * @param  obj the object whose elements will be obtained.
    * @return a Hashtable containing the element name (as key) and Element object containign the type (ie class) and the value).
    * @see Hashtable
    * @see Element
    */
    public Hashtable<String, Element> getAvailableValues(Object obj) throws Exception {
        Class c = obj.getClass();
        //Method[] m = c.getMethods();
        Vector ve = retrieveMethods(obj.getClass(), null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        String name, retval;
        Hashtable<String, Element> h = new Hashtable<String, Element>();

        for (int i = 0; i < m.length; i++) {
            name = m[i].getName();
            retval = m[i].getReturnType().getName();

            if (retval.equalsIgnoreCase("void") && name.startsWith("set")) {

                // we get the method name
                String field = name.substring(3);
                String getter = (m[i].getParameterTypes()[0].getSimpleName().equals("boolean") ? "is" : "get")
                        + field;
                try {
                    Method met = c.getMethod(getter, (Class[]) null);
                    Object o = null;
                    String retype = null;
                    try {
                        retype = met.getReturnType().getSimpleName();
                        o = met.invoke(obj, (Object[]) null);
                    } catch (Exception g) {
                        g.printStackTrace();
                    }

                    if (o != null) {
                        if (retype.endsWith("Date")) {
                            h.put(field, new Element(retype, (new SimpleDateFormat(_dateformat)).format((Date) o)));
                        } else if (retype.endsWith("byte[]")) {
                            //h.put(field,new Element(retype,(byte[])o));
                            h.put(field, new Element(retype, Base64.decodeBase64((byte[]) o)));
                        } else if (retype.endsWith("Serializable")) {
                            h.put(field, new Element(retype, (Serializable) o));
                        } else {
                            h.put(field, new Element(retype, o.toString()));
                        }
                    }
                } catch (Exception f) {
                    f.printStackTrace();
                    // attempt a get.
                }
            }
        }

        return h;
    }

    /**
    * retrieves all possible elements and values of an XML file (string).
    * 
    * @param  content the XML whose elements will be obtained.
    * @return a Hashtable containing the element name (as key) and Element object containign the type (ie class and the value).
    * @see Hashtable
    * @see Element
    */
    public Hashtable<String, Element> getAvailableValues(String content) throws Exception {
        Hashtable<String, Element> h = new Hashtable<String, Element>();

        XMLConfiguration x = new XMLConfiguration();
        x.setDelimiterParsingDisabled(true);
        x.load(new ByteArrayInputStream(content.getBytes()));
        Iterator it = x.getKeys();
        String method = null;
        String type = null;

        boolean hasmethod = false;
        while (it.hasNext()) {
            String s = (String) it.next();
            // make sure they have the same type?
            if (s.contains("[@")) {
                type = x.getString(s);
                if (!hasmethod) // then must be empty
                {
                    h.put(s.substring(0, s.indexOf("[")), new Element(type, ""));
                    type = null;
                    method = null;
                }
            } else {
                hasmethod = true;
                method = s;
            }

            if (type != null && method != null) {
                if (type.endsWith("Date")) {
                    h.put(method,
                            new Element(type, (new SimpleDateFormat(_dateformat)).parse(x.getString(method))));
                } else if (type.endsWith("byte[]")) {
                    h.put(method, new Element(type, (byte[]) Base64.decodeBase64(x.getString(method).getBytes())));
                } else if (type.endsWith("Serializable")) {
                    h.put(method, new Element(type,
                            (Serializable) getObject(Base64.decodeBase64(x.getString(method).getBytes()))));
                } else {
                    h.put(method, new Element(type, x.getString(method)));
                }
                type = null;
                method = null;
                hasmethod = false;
            }
        }

        return h;
    }

    // values should contain the existing values from the DB.. this method will get the possible methods from the passed object
    // and put it in the values hashtable.
    /**
    * adds the elements of a given object to an existing hashtable of elements and values. This method is used specifically for merging contents
    * from an existing record and an updated object.
    * 
    * @param  values table of existing elements and their values.
    * @param  obj object whose elements will be retrieved and added to the values table.
    * @see Hashtable
    * @see Element
    */
    public void softTransfer(Hashtable values, Object obj) throws Exception {
        Class c = obj.getClass();
        //Method[] m = c.getMethods();
        Vector ve = retrieveMethods(obj.getClass(), null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        String name, retval;

        for (int i = 0; i < m.length; i++) {

            name = m[i].getName();
            retval = m[i].getReturnType().getName();
            if (retval.equalsIgnoreCase("void") && name.startsWith("set")) {
                // we get the method name
                String field = name.substring(3);
                String getter = (m[i].getParameterTypes()[0].getSimpleName().equals("boolean") ? "is" : "get")
                        + field;
                try {
                    Method met = c.getMethod(getter, (Class[]) null);
                    String retype = met.getReturnType().getSimpleName(); // get the return so we know what type to put in the setXXX

                    Object val = null;
                    try {
                        val = met.invoke(obj, (Object[]) null); // finally insert the value
                    } catch (Exception g) {
                        g.printStackTrace();
                    }

                    field = field.toLowerCase();

                    if (val != null) {
                        if (retype.endsWith("Date")) {
                            values.put(field, new Element(retype, (Date) val));
                        } else if (retype.endsWith("byte[]")) {
                            values.put(field, new Element(retype, (byte[]) val));
                        } else if (retype.toLowerCase().endsWith("boolean")) {
                            values.put(field, new Element(retype, (Boolean) val));
                        } else {
                            values.put(field, new Element(retype, val.toString()));
                        }
                    } else {
                        // we allow null values
                        values.put(field, new Element(retype, null));
                    }

                } catch (Exception f) {
                    f.printStackTrace();
                    // attempt a get.
                }
            }
        }

    }

    /**
    * obtains the XML equivalent of the elements and its values found in the passed hashtable and set the root element name to the class name of
    * the passed object.
    *
    * @param  obj describes the XML to be produced.
    * @param  h table containing the elements that will be used to populate the XML.
    * @return XML string.
    * @see Hashtable
    * @see Element
    */
    public String getXML(Object obj, Hashtable h) throws Exception {
        Class c = obj.getClass();
        StringBuffer xml = new StringBuffer();
        xml.append("<" + c.getSimpleName().toLowerCase() + ">");

        Enumeration e = h.keys();
        while (e.hasMoreElements()) {
            String field = ((String) e.nextElement()).toLowerCase();
            Element el = (Element) h.get(field);

            if (el.getContent() != null) {
                if (indexable(el.getType()) && !el.getType().equals("byte[]")) {
                    if (el.getType().endsWith("Date")) {
                        // might be empty!
                        if ((el.getContent() + "").trim().startsWith("0003-11-30T00:00:00")) {
                            xml.append(
                                    "<" + field + " type=\"" + el.getType() + "\"><![CDATA[ ]]></" + field + ">");
                        } else {

                            String dt = (new SimpleDateFormat(_dateformat)).format((Date) el.getContent());
                            dt = dt.replaceFirst("00:00:00", "");
                            xml.append("<" + field + " type=\"" + el.getType() + "\"><![CDATA[" + dt + "]]></"
                                    + field + ">");

                        }

                    } else if (el.getType().endsWith("XMLGregorianCalendar")) {
                        // 2009-01-01T10:00:00.000+08:00
                        // might be empty!
                        if ((el.getContent() + "").trim().startsWith("0003-11-30T00:00:00")) {
                            xml.append(
                                    "<" + field + " type=\"" + el.getType() + "\"><![CDATA[ ]]></" + field + ">");
                        } else {
                            String sd = (el.getContent() + "").trim();
                            if (sd.length() == 10) {
                                sd = sd + "T00:00:00.000";
                            }
                            Date d = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S")).parse(sd);

                            String dt = (new SimpleDateFormat(_dateformat)).format(d);
                            dt = dt.replaceFirst("00:00:00", "");
                            xml.append("<" + field + " type=\"" + el.getType() + "\"><![CDATA[" + dt + "]]></"
                                    + field + ">");
                        }
                    } else {
                        xml.append("<" + field + " type=\"" + el.getType() + "\"><![CDATA["
                                + replaceString(el.getContent().toString(), "%", "&amp;#037;") + "]]></" + field
                                + ">");
                    }
                } else if (el.getType().endsWith("byte[]")) {
                    xml.append("<" + field + " type=\"" + el.getType() + "\"><![CDATA["
                            + new String((byte[]) el.getContent()) + "]]></" + field + ">");
                }
            } else {
                xml.append("<" + field + " type=\"" + el.getType() + "\"></" + field + ">");
            }
        }

        xml.append("</" + c.getSimpleName().toLowerCase() + ">");

        return xml.toString();

    }

    /**
    * obtains the XML equivalent of the elements and its values found in the passed object. 
    * 
    * @param  classname name of the class that will be used as the root element for this object, if null it will use the objects natural class name.
    * @param  obj the object containing the elements that will be used to populate the XML.
    * @param  includeflextag true if the final XML will include the tag or not.
    * @param  usefilename set to true if the object you're passing (ie is only relevant) has a binary (ie byte array) field and you want to overried the field content to contain the filename instead of the actual byte array string.
    * @return XML string.
    * @see Hashtable
     *@see Element
    */
    static public String getXML(String classname, Object obj, boolean includeflextag, boolean usefilename)
            throws Exception {
        Class c = obj.getClass();
        //Method[] m = c.getMethods();
        Vector ve = retrieveMethods(obj.getClass(), null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        String name, retval;
        StringBuilder main = new StringBuilder();
        String id = null;
        String parentid = null;

        if (c.getSimpleName().endsWith("Class")) {
            return "";
        }

        if (classname == null) {
            classname = c.getSimpleName();
        }

        classname = classname.toLowerCase();

        StringBuffer xml = new StringBuffer();

        for (int i = 0; i < m.length; i++) {
            name = m[i].getName();
            retval = m[i].getReturnType().getName();

            if (retval.equalsIgnoreCase("void") && name.startsWith("set")) {
                // we get the method name
                String field = name.substring(3);
                String getter = (m[i].getParameterTypes()[0].getSimpleName().equals("boolean") ? "is" : "get")
                        + field;

                try {

                    Method met = c.getMethod(getter, (Class[]) null);
                    Object o = null;
                    try {
                        o = met.invoke(obj, (Object[]) null);
                    } catch (Exception g) {
                        // no content                        
                    }

                    field = field.toLowerCase();

                    //System.out.println(i+">>>> name "+name+" field:"+field+" type:"+t+" "+o);
                    if (o != null) {
                        String t = met.getReturnType().getSimpleName();
                        if (t.endsWith("Date")) {
                            if ((o + "").trim().startsWith("0003-11-30T00:00:00")) {
                                xml.append("<" + field + " type=\"" + t + "\"><![CDATA[ ]]></" + field + ">");
                            } else {
                                String dt = ((new SimpleDateFormat(_dateformat)).format((Date) o));
                                dt = dt.replaceFirst("00:00:00", "");
                                xml.append(
                                        "<" + field + " type=\"" + t + "\"><![CDATA[" + dt + "]]></" + field + ">");
                            }

                        } else if (t.endsWith("XMLGregorianCalendar")) {
                            // 2009-01-01T10:00:00.000+08:00
                            if ((o + "").trim().startsWith("0003-11-30T00:00:00")) {
                                xml.append("<" + field + " type=\"" + t + "\"><![CDATA[ ]]></" + field + ">");
                            } else {

                                Date d = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S")).parse(o + "");

                                String dt = (new SimpleDateFormat(_dateformat)).format(d);
                                dt = dt.replaceFirst("00:00:00", "");
                                xml.append(
                                        "<" + field + " type=\"" + t + "\"><![CDATA[" + dt + "]]></" + field + ">");

                            }

                        } else if (t.endsWith("byte[]")) {

                            if (usefilename) {
                                FileContainer fc = extractFileFromMimeMessage((byte[]) o);

                                xml.append("<" + field + " type=\"" + t + "\"><![CDATA["
                                        + (fc == null || fc.getFileName() == null ? "" : fc.getFileName()) + "]]></"
                                        + field + ">");
                            } else {
                                xml.append("<" + field + " type=\"" + t + "\"><![CDATA[" + new String((byte[]) o)
                                        + "]]></" + field + ">");
                                //xml.append("<"+field+" type=\""+t+"\"><![CDATA["+new String(fc.getByteArray())+"]]></"+field+">");
                            }
                        } else if (t.toLowerCase().endsWith("boolean")) {
                            xml.append("<" + field + " type=\"" + t + "\"><![CDATA[" + o + "]]></" + field + ">");
                        } else {
                            if (indexable(t)) {
                                if (field.equals("id")) {
                                    id = o.toString();
                                } else if (field.equals("parentid")) {
                                    parentid = o.toString();
                                } else {
                                    // 2013-01-15 yujb reverted to not replacing '%' with &amp;#037;
                                    xml.append("<" + field + " type=\"" + t + "\"><![CDATA[" + o.toString()
                                            + "]]></" + field + ">");
                                    //xml.append("<"+field+" type=\""+t+"\"><![CDATA["+replaceString(o.toString(),"%","&amp;#037;")+"]]></"+field+">");                                  
                                }
                            } else {
                                if (c.getSimpleName().endsWith("FlexContainer") && field.equals("object")) {
                                    xml.append(getXML(null, o, false, usefilename));
                                }
                            }
                        }
                    } else {
                        xml.append("<" + field + " type=\"" + met.getReturnType().getSimpleName() + "\"/>");
                    }
                } catch (Exception f) {
                    //throw f;
                    f.printStackTrace();
                    // attempt a get.
                }
            } else {

                // what if this is a list?
                if (retval.endsWith("List")) {
                    String getter = m[i].getName();
                    Method met = c.getMethod(getter, (Class[]) null);
                    List o = null;
                    try {
                        o = (List) met.invoke(obj, (Object[]) null);
                    } catch (Exception g) {
                        // no content
                        g.printStackTrace();
                    }

                    if (o != null) {
                        Iterator it = o.iterator();
                        while (it.hasNext()) {
                            Object lo = it.next();
                            xml.append(getXML(null, lo, false, usefilename));
                        }
                    }
                } else if (retval.endsWith("ConcurrentHashMap")) {
                    String getter = m[i].getName();
                    Method met = c.getMethod(getter, (Class[]) null);
                    ConcurrentHashMap o = null;
                    try {
                        o = (ConcurrentHashMap) met.invoke(obj, (Object[]) null);
                    } catch (Exception g) {
                        // no content
                        g.printStackTrace();
                    }

                    if (o != null) {
                        Enumeration en = o.keys();
                        while (en.hasMoreElements()) {
                            String el = (String) en.nextElement();
                            Vector<FlexContainer> children = (Vector<FlexContainer>) o.get(el);
                            Iterator it = children.iterator();
                            xml.append("<" + el + "typerecords total=\"" + children.size() + "\" from=\"0\" to=\""
                                    + children.size() + "\" returned=\"" + children.size() + "\"/>");
                            xml.append("<" + el + "typelist>");

                            while (it.hasNext()) {
                                FlexContainer lo = (FlexContainer) it.next();
                                xml.append("<flexcontainer id=\"" + lo.getId() + "\" parentid=\"" + lo.getParentId()
                                        + "\">" + getXML(null, lo, false, usefilename) + "</flexcontainer>");
                            }
                            xml.append("</" + el + "typelist>");
                        }
                    }
                } else {
                    if (!name.startsWith("get") && !retval.startsWith("java") && !retval.endsWith("byte[]")
                            && !retval.equals("int") && !retval.equals("boolean") && !retval.equals("void")) // if complex
                    {
                        String getter = m[i].getName();
                        Method met = c.getMethod(getter, (Class[]) null);
                        Object o = null;
                        try {
                            o = met.invoke(obj, (Object[]) null);
                        } catch (Exception g) {
                            // no content
                            g.printStackTrace();
                        }
                        //System.out.println(i+">>>> name "+name+" field:"+getter.substring(3)+" retval:"+retval+" "+o);
                        if (o != null) {
                            xml.append(getXML(getter.substring(3), o, false, usefilename));
                        }
                    }
                }
            }
        }

        // then we get the complex types!
        /*Field[] f = c.getDeclaredFields();
        for (int i=0;i<f.length;i++)
        {
        String pname = f[i].getType().getSimpleName();
        if (pname.equals("List"))
        {
            Type type = f[i].getGenericType();
            ParameterizedType t = (ParameterizedType)type;
            Class c1 = (Class) t.getActualTypeArguments()[0];
            String getter = f[i].getName();
            String n = (getter.substring(0,1).toUpperCase())+getter.substring(1);
            getter = "get"+n;
            
            Method met = c.getMethod(getter, (Class[])null);
            List o = null;
            try
            {
                o = (List) met.invoke(obj,(Object[])null);
            }
            catch (Exception g)
            {
                // no content
                g.printStackTrace();
            }
            
            if (o!=null)
            {
                Iterator it = o.iterator();
                while (it.hasNext())
                {
                    Object lo = it.next();
                    xml.append(getXML(n,lo,false));
                }
            }
            
        }
        else
        {
        }
        }*/

        // then we check for parent classes
        // check for superclass
        /*Class sc = c.getSuperclass();
        if (!sc.getSimpleName().equals("Object"))
        {
        xml.append(getXML(sc.getName(),sc.newInstance(),false));
        }*/

        if (!c.getSimpleName().endsWith("FlexContainer")) {
            //main.append("<"+classname+" id=\""+id+"\">");
            main.append("<" + classname + ">");
            xml.append("</" + classname + ">");
        }

        if (includeflextag) {
            if (c.getSimpleName().equals("FlexContainer")) {
                main.append("<" + classname + " id=\"" + id + "\" parentid=\"" + parentid + "\">");
            } else {
                main.append("<" + classname + ">");
            }
            main.append(xml);
            main.append("</flexcontainer>");
        } else {
            main.append(xml);
        }
        //System.out.println("\n>>>>\n"+main+"\n<<<<<");
        return main.toString();

    }

    /**
    * extracts the plain XML equivalent of the passed object.
    *
    * @param  obj the object containing the elements that will be used to populate the XML.
    * @return XML string.
    * @see Hashtable
     *@see Element
    */
    static public String getSimpleXML(Object obj) throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        JAXBContext context = JAXBContext.newInstance(((FlexContainer) obj).getObject().getClass());
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        m.marshal(new JAXBElement(new QName("", ((FlexContainer) obj).getObject().getClass().getSimpleName()),
                ((FlexContainer) obj).getObject().getClass(), ((FlexContainer) obj).getObject()), bos);
        return new String(bos.toByteArray());
    }

    /**
    * obtains the XML equivalent of the elements in a collection and its values found in the passed object.
    *
    * @param  obj a collection object containing the elements that will be used to populate the XML.
    * @return XML string.
    * @see Collection
    */
    static public String getCollectionXML(Collection v) throws Exception {
        return getCollectionXML(v, "LIST");
    }

    static public String getCollectionXML(Collection v, String listname) throws Exception {
        StringBuffer xml = new StringBuffer("<" + listname + " count=\"" + v.size() + "\">\n");
        Iterator en = v.iterator();
        while (en.hasNext()) {
            xml.append(getXML(null, en.next(), true, true) + "\n");
        }
        xml.append("</" + listname + ">");
        return xml.toString();

    }

    /**
    * obtains an XSL prototype for the object.
    *
    * @param  title optional title in the XSL prorotype, can be null (ie none).
    * @param  config configuration for class type.
    * @param  obj the object containing the elements that will be used to populate the XSL.
    * @param  listtype set to '0' if its not a list type, 1 for regular list and 2 if this is a child list .
    * @param  type 0 for non-edit viewing only, 1 to embed viewable contents in editable fields (ie for updating or editing) and 2 for empty fields (ie for new records).
    * @param  message default message.
    * @param  parentclass parentclassname for reference.
    * @return XSL string.
    * @see Hashtable
    *@see Element
    */
    public String getXSLPrototype(String title, Config config, Object obj, boolean list, int type, String message,
            String parentclass) throws Exception {
        Class c = obj.getClass();

        String simplename = c.getSimpleName();
        simplename = simplename.substring(0, simplename.length() - 4);

        ConfigElement ce = config.getElementConfig(c.getSimpleName());

        Vector ve = retrieveMethods(c, null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        String name, retval;
        String id = null;
        String parentid = null;
        StringBuffer xml = new StringBuffer();
        StringBuffer listheader = new StringBuffer();
        Hashtable fields = getFields(obj);

        Enumeration it = fields.keys();

        if (list) {

            String callname = parentclass == null ? "list" + c.getSimpleName() + ".igx"
                    : "get" + c.getSimpleName() + "WithParentID.igx";
            String idref = parentclass == null ? "{../@id}" : "<%var_request[id]%>";

            xml.append("\n\n<xsl:template match=\"records\">\n");
            //xml.append("<div class=\"info\">\n");
            xml.append("<div>\n");

            // must be a child!
            if (parentclass != null) {
                xml.append("<span style=\"font-size:14px;font-weight:bold\">\n");
                xml.append("    <a onClick=\"javascript:linkchangecontent('<%var_context["
                        + parentclass.toLowerCase() + "parent]%>?id=<%var_context[" + parentclass.toLowerCase()
                        + "parentid]%>','contentdyn')\" href=\"#\">\n");
                xml.append("    <%var_context[" + parentclass.toLowerCase() + "parentname]%>\n");
                xml.append("    </a>\n");
                xml.append("</span>\n");

            }

            xml.append("<span style=\"float:right;padding-right:3px\">\n");
            xml.append("\n");
            xml.append("<!-- TOP -->\n");
            xml.append(" <xsl:choose>\n");
            xml.append("      <xsl:when test=\"number(@from) &gt; 0\">\n");
            xml.append("      <a onClick=\"javascript:linkchangecontent('" + callname + "?id=" + idref
                    + "&amp;from=0&amp;to=15','contentdyn')\" href=\"#\">\n");
            xml.append("      <img src=\"images/top.png\" alt=\"Top\"/>\n");
            xml.append("      </a> \n");
            xml.append("      </xsl:when>\n");
            xml.append("      <xsl:otherwise>\n");
            xml.append("      <img src=\"images/topg.png\" alt=\"Top\"/>\n");
            xml.append("      </xsl:otherwise>\n");
            xml.append(" </xsl:choose>\n");
            xml.append("\n");
            xml.append("<!-- PREV -->\n");
            xml.append("<xsl:choose>\n");
            xml.append("      <xsl:when test=\"@from &gt; 0\">\n");
            xml.append("         <xsl:choose>\n");
            xml.append("         <xsl:when test=\"(number(@from)-15) &lt; 0\">\n");
            xml.append("         <a onClick=\"javascript:linkchangecontent('" + callname + "?id=" + idref
                    + "&amp;from=0&amp;to=15','contentdyn')\" href=\"#\">\n");
            xml.append("         <img src=\"images/prev.png\" alt=\"Previous\"/>\n");
            xml.append("         </a> \n");
            xml.append("         </xsl:when>\n");
            xml.append("         <xsl:otherwise>\n");
            xml.append("         <a onClick=\"javascript:linkchangecontent('" + callname + "?id=" + idref
                    + "&amp;from={number(@from)-15}&amp;to={@from}','contentdyn')\" href=\"#\">\n");
            xml.append("         <img src=\"images/prev.png\" alt=\"Previous\"/>\n");
            xml.append("         </a> \n");
            xml.append("         </xsl:otherwise>\n");
            xml.append("         </xsl:choose>\n");
            xml.append("      </xsl:when>\n");
            xml.append("      <xsl:otherwise>\n");
            xml.append("      <img src=\"images/prevg.png\" alt=\"Previous\"/>\n");
            xml.append("      </xsl:otherwise>\n");
            xml.append("</xsl:choose>\n");
            xml.append("<!-- NEXT -->\n");
            xml.append("<xsl:choose>\n");
            xml.append("      <xsl:when test=\"(number(@from)+15) &lt; number(@total)\">\n");
            xml.append("         <xsl:choose>\n");
            xml.append("         <xsl:when test=\"(number(@from)+15) &gt; number(@total)\">\n");
            xml.append("         <a  onClick=\"javascript:linkchangecontent('" + callname + "?id=" + idref
                    + "&amp;from={number(@from)+15}&amp;to={@total}','contentdyn')\" href=\"#\">\n");
            xml.append("         <img src=\"images/next.png\" alt=\"Next\"/>\n");
            xml.append("         </a> \n");
            xml.append("         </xsl:when>\n");
            xml.append("         <xsl:otherwise>\n");
            xml.append("         <a onClick=\"javascript:linkchangecontent('" + callname + "?id=" + idref
                    + "&amp;from={number(@from)+15}&amp;to={number(@from)+30}','contentdyn')\" href=\"#\">\n");
            xml.append("         <img src=\"images/next.png\" alt=\"Next\"/>\n");
            xml.append("         </a> \n");
            xml.append("         </xsl:otherwise>\n");
            xml.append("         </xsl:choose>\n");
            xml.append("      </xsl:when>\n");
            xml.append("      <xsl:otherwise>\n");
            xml.append("      <img src=\"images/nextg.png\" alt=\"Next\"/>\n");
            xml.append("      </xsl:otherwise>\n");
            xml.append("</xsl:choose>\n");
            xml.append("<!-- BOTTOM -->\n");
            xml.append("<xsl:choose>\n");
            xml.append("      <xsl:when test=\"number(@from) &lt; (number(@total)-15)\">\n");
            xml.append("         <xsl:choose>\n");
            xml.append("         <xsl:when test=\"number(@total) &gt; 15\">\n");
            xml.append("         <a onClick=\"javascript:linkchangecontent('" + callname + "?id=" + idref
                    + "&amp;from={number(@total)-15}&amp;to={@total}','contentdyn')\" href=\"#\">\n");
            xml.append("         <img src=\"images/bottom.png\" alt=\"Bottom\"/>\n");
            xml.append("         </a> \n");
            xml.append("         </xsl:when>\n");
            xml.append("         <xsl:otherwise>\n");
            xml.append("         <a onClick=\"javascript:linkchangecontent('" + callname + "?id=" + idref
                    + "&amp;from={number(@from)+15}&amp;to={number(@from)+30}','contentdyn')\" href=\"#\">\n");
            xml.append("         <img src=\"images/bottom.png\" alt=\"Bottom\"/>\n");
            xml.append("         </a> \n");
            xml.append("         </xsl:otherwise>\n");
            xml.append("         </xsl:choose>\n");
            xml.append("      </xsl:when>\n");
            xml.append("      <xsl:otherwise>\n");
            xml.append("      <img src=\"images/bottomg.png\" alt=\"Bottom\"/>\n");
            xml.append("      </xsl:otherwise>\n");
            xml.append("</xsl:choose>\n");
            xml.append("</span>\n");

            xml.append("<span style=\"float:right;vertical-align:middle;padding-right:3px\">\n");
            xml.append("<xsl:choose>\n");
            xml.append("   <xsl:when test=\"number(@total) &gt; 0\">\n");
            xml.append("    Showing <xsl:value-of select=\"number(@from)+1\"/>\n");
            xml.append(
                    "    to <xsl:value-of select=\"number(@from)+number(@returned)\"/> records of <xsl:value-of select=\"@total\"/>\n");
            xml.append("   </xsl:when>\n");
            xml.append("   <xsl:otherwise>\n");
            xml.append("     No Records.\n");
            xml.append("   </xsl:otherwise>\n");
            xml.append("</xsl:choose>\n");
            xml.append("</span>\n");
            xml.append("\n");

            xml.append("</div>\n");
            xml.append("</xsl:template>\n\n");

            xml.append("\n<xsl:template match=\"LIST\">\n");

            /*if (title!=null)
            {
            xml.append("<div class=\"info\"><strong>"+title+"</strong> (found <xsl:value-of select=\"@COUNT\"/> records)</div>\n");
            }*/

            xml.append("<table class=\"sortable\">\n");

            // create the header
            xml.append("          <!-- create the header -->\n");
            xml.append("          <thead><tr>\n");

            if (ce != null) {
                Map cef = ce.getFields();
                Iterator itr = cef.values().iterator();
                while (itr.hasNext()) {
                    ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                    if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                        xml.append("               <th>" + cfi.label + "</th>\n");
                    }
                }
            } else {
                while (it.hasMoreElements()) {
                    String f = (String) it.nextElement();
                    xml.append("               <th>" + f + "</th>\n");
                }

            }
            xml.append("               <th>Action</th>\n");
            xml.append("          </tr></thead>\n");

            xml.append("          <xsl:apply-templates select=\"flexcontainer/" + c.getSimpleName().toLowerCase()
                    + "\"/>\n");
            xml.append("</table>\n");
            xml.append("</xsl:template>\n");

            // create the table contents

            xml.append("<xsl:template match=\"flexcontainer/" + c.getSimpleName().toLowerCase() + "\">");
            xml.append("\n          <!-- create table contents -->\n");
            xml.append("  <xsl:for-each select=\".\">\n");
            xml.append("          <tr>\n");

            if (ce != null) {
                Map cef = ce.getFields();
                Iterator itr = cef.values().iterator();
                while (itr.hasNext()) {
                    ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();

                    if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type.toLowerCase()) > -1) {
                        if (type == 0) {
                            if (cfi.type.equals("byte[]") || cfi.type.equals("file")
                                    || cfi.type.equalsIgnoreCase("base64Binary")) {
                                xml.append("               <td><a href=\"get" + cfi.name + "In" + c.getSimpleName()
                                        + ".igx?id={../@id}\"><xsl:value-of select=\"" + cfi.name.toLowerCase()
                                        + "\"/></a></td>\n");
                            } else {
                                //format-number(units,'###,###,##0.00')
                                if (cfi.type.equalsIgnoreCase("decimal")) {
                                    xml.append("               <td><xsl:value-of select=\"format-number("
                                            + cfi.name.toLowerCase() + ",'###,###,##0.00')\"/></td>\n");
                                } else {
                                    xml.append("               <td><xsl:value-of select=\"" + cfi.name.toLowerCase()
                                            + "\"/></td>\n");
                                }
                            }

                        } else if (type == 1) {
                            xml.append("               <td><input class=\"txt\" id=\"text" + cfi.name + "\" name=\""
                                    + cfi.name.toLowerCase() + "\" type=\"text\" value=\"{" + cfi.name
                                    + "}\"/></td>\n");
                        } else {
                            xml.append("               <td><input class=\"txt\" id=\"text" + cfi.name + "\" name=\""
                                    + cfi.name.toLowerCase() + "\" type=\"text\" value=\"\"/></td>\n");
                        }
                    }
                }
            } else {
                it = fields.keys();
                while (it.hasMoreElements()) {
                    String f = (String) it.nextElement();
                    String t = (String) fields.get(f);

                    if (type == 0) {
                        if (t.equals("byte[]") || t.equals("base64Binary")) {
                            xml.append("               <td><a href=\"get" + f + "In" + c.getSimpleName()
                                    + ".igx?id={../@id}\"><xsl:value-of select=\"" + f.toLowerCase()
                                    + "\"/></a></td>\n");
                        } else {
                            //format-number(units,'###,###,##0.00')
                            if (t.equalsIgnoreCase("decimal")) {
                                xml.append("               <td><xsl:value-of select=\"format-number("
                                        + f.toLowerCase() + ",'###,###,##0.00')\"/></td>\n");
                            } else {
                                xml.append("               <td><xsl:value-of select=\"" + f.toLowerCase()
                                        + "\"/></td>\n");
                            }
                        }

                    } else if (type == 1) {
                        xml.append("               <td><input class=\"txt\" id=\"text" + f + "\" name=\""
                                + f.toLowerCase() + "\" type=\"text\" value=\"{" + f.toLowerCase()
                                + "}\"/></td>\n");
                    } else {
                        xml.append("               <td><input class=\"txt\" id=\"text" + f + "\" name=\""
                                + f.toLowerCase() + "\" type=\"text\" value=\"\"/></td>\n");
                    }

                }

            }

            xml.append("               <td>\n");

            /*if (parentclass!=null)
            {
            xml.append("                    <a onClick=\""+(message!=null?"javascript:hidedivDisplay('message');":"")+"javascript:linkchangecontent('get"+c.getSimpleName()+".igx?id={../@id}&amp;do=savecontext&amp;"+parentclass.toLowerCase()+"parent=get"+parentclass+".igx&amp;"+parentclass.toLowerCase()+"parentname="+parentclass+"&amp;"+parentclass.toLowerCase()+"parentid=<%var_request[id]%>','contentdyn')\" href=\"#\">View</a> | \n");
            xml.append("                    <a href=\"javascript:getConfirmation('Are You Sure You Want to Delete this Record?','delete"+c.getSimpleName()+".igx?id={../@id}&amp;do=savecontext&amp;"+parentclass.toLowerCase()+"parent=get"+parentclass+".igx&amp;"+parentclass.toLowerCase()+"parentname="+parentclass+"&amp;"+parentclass.toLowerCase()+"parentid=<%var_request[id]%>','')\">Delete</a>\n");
                
            }
            else
            {*/
            xml.append("                    <a onClick=\""
                    + (message != null ? "javascript:hidedivDisplay('message');" : "")
                    + "javascript:linkchangecontent('get" + c.getSimpleName()
                    + ".igx?id={../@id}','contentdyn')\" href=\"#\">View</a> | <a href=\"javascript:getConfirmation('Are You Sure You Want to Delete this Record?','delete"
                    + c.getSimpleName() + ".igx?id={../@id}','')\">Delete</a>\n");
            //}

            xml.append("               </td>\n");
            xml.append("          </tr>\n");
            xml.append("  </xsl:for-each>\n");
            xml.append("</xsl:template>\n");
        } else {

            // for viewing and editing only
            if (type < 2) {
                xml.append("\n<xsl:template match=\"flexcontainer/" + c.getSimpleName().toLowerCase() + "\">\n\n");

                if (parentclass == null) {
                    xml.append("<!-- Printer Friendly Version -->\n");
                    xml.append("<div align=\"right\">\n");
                    xml.append("     <a href=\"javascript:"
                            + (message != null ? "javascript:hidedivDisplay('message');" : "")
                            + "javascript:window.location='get" + c.getSimpleName()
                            + "AsXML.igx?id={../@id}';\"> <img src=\"images/xml.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"XML\"></img></a>\n");
                    xml.append("     <a href=\"javascript:" + (message != null ? "hidedivDisplay('message');" : "")
                            + "javascript:printClick('Print " + c.getSimpleName() + "','print" + c.getSimpleName()
                            + "','printlist" + c.getSimpleName()
                            + "')\"> <img src=\"images/printer.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"Print Version\"></img></a>\n");
                    xml.append("</div>\n");
                    xml.append("\n\n");
                } else {
                    xml.append("<!-- Printer Friendly and XML Version, uncomment to enable printing -->\n");
                    xml.append("<!-- <div align=\"right\">\n");
                    xml.append("     <a href=\"javascript:"
                            + (message != null ? "javascript:hidedivDisplay('message');" : "")
                            + "javascript:window.location='get" + c.getSimpleName()
                            + "AsXML.igx?id={../@id}';\"> <img src=\"images/xml.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"XML\"></img></a>\n");
                    xml.append("     <a href=\"javascript:" + (message != null ? "hidedivDisplay('message');" : "")
                            + "javascript:printClick('Print " + c.getSimpleName() + "','print" + c.getSimpleName()
                            + "','printlist" + c.getSimpleName()
                            + "')\"> <img src=\"images/printer.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"Print Version\"></img></a>\n");
                    xml.append("</div>\n");
                    xml.append("-->\n\n");
                    xml.append("<span style=\"font-size:14px;font-weight:bold\">\n");
                    xml.append("    <a onClick=\"javascript:linkchangecontent('<%var_context["
                            + parentclass.toLowerCase() + "parent]%>?id=<%var_context[" + parentclass.toLowerCase()
                            + "parentid]%>','contentdyn')\" href=\"#\">\n");
                    xml.append("    <%var_context[" + parentclass.toLowerCase() + "parentname]%>\n");
                    xml.append("    </a>\n");
                    xml.append("</span>\n\n");
                }

                // generate the view prototype first
                xml.append("<!--- START OF view" + c.getSimpleName() + " CODE SEGMENT -->\n");
                xml.append("<div id=\"view" + c.getSimpleName() + "\">\n\n");

                if (message != null) {
                    xml.append("<div class=\"info\" id=\"message\"><b>" + message + "</b></div>\n\n");
                }

                xml.append("<fieldset>\n");

                xml.append("<legend>View " + simplename + "</legend>\n");

                xml.append("<div class=\"fieldsetwrap\">\n");

                xml.append("     <div class=\"datafieldwrap\">\n");
                xml.append("     <table class=\"datafield\">\n");

                if (ce != null) {
                    Map cef = ce.getFields();

                    Iterator itr = cef.values().iterator();
                    while (itr.hasNext()) {
                        ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();

                        if (cfi.visible && _types.indexOf(cfi.type) > -1) {
                            if (cfi.type.equals("byte[]") || cfi.type.equals("file")
                                    || cfi.type.equals("base64Binary")) {
                                xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                        + ":</td><td class=\"data full\"><a href=\"get" + cfi.name + "In"
                                        + c.getSimpleName() + ".igx?id={../@id}\"><xsl:value-of select=\""
                                        + cfi.name.toLowerCase() + "\"/></a></td></tr>\n");
                            } else {
                                if (cfi.type.equalsIgnoreCase("decimal")) {
                                    xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\"><xsl:value-of select=\"format-number("
                                            + cfi.name.toLowerCase() + ",'###,###,##0.00')\"/></td></tr>\n");
                                } else {
                                    xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\"><pre><xsl:value-of select=\""
                                            + cfi.name.toLowerCase() + "\"/></pre></td></tr>\n");
                                }
                            }
                        }
                    }
                } else {

                    while (it.hasMoreElements()) {
                        String f = (String) it.nextElement();
                        String t = (String) fields.get(f);

                        if (t.equals("byte[]")) {
                            xml.append("          <tr><td class=\"lbl\">" + f
                                    + ":</td><td class=\"data full\"><a href=\"get" + f + "In" + c.getSimpleName()
                                    + ".igx?id={../@id}\"><xsl:value-of select=\"" + f.toLowerCase()
                                    + "\"/></a></td></tr>\n");
                        } else {
                            if (t.equalsIgnoreCase("decimal")) {
                                xml.append("          <tr><td class=\"lbl\">" + f
                                        + ":</td><td class=\"data full\"><xsl:value-of select=\"format-number("
                                        + f.toLowerCase() + ",'###,###,##0.00')\"/></td></tr>\n");
                            } else {
                                xml.append("          <tr><td class=\"lbl\">" + f
                                        + ":</td><td class=\"data full\"><pre><xsl:value-of select=\""
                                        + f.toLowerCase() + "\"/></pre></td></tr>\n");
                            }

                        }
                    }

                }

                xml.append("     </table>\n");
                xml.append("     </div>\n");
                xml.append("</div>\n");
                xml.append("</fieldset>\n\n");

                xml.append("<div class=\"btnrow\">\n");
                xml.append("     <input type=\"button\" value=\"Edit\" onClick=\""
                        + (message != null ? "hidedivDisplay('message');" : "") + "hidedivDisplay('view"
                        + c.getSimpleName() + "');showdivDisplay('edit" + c.getSimpleName() + "');\"/>\n");
                xml.append("     <input type=\"button\" value=\"Delete\" onClick=\""
                        + (message != null ? "hidedivDisplay('message');" : "")
                        + "getConfirmation('Are You Sure You Want to Delete this Record?','delete"
                        + c.getSimpleName() + ".igx?id={../@id}','')\"/>\n");
                xml.append("</div>\n\n");
                xml.append("</div>\n");
                xml.append("<div class=\"clear\"></div>\n");
                xml.append("<!--- END OF view" + c.getSimpleName() + " CODE SEGMENT -->\n\n");

            }

            if (type < 2) // if it also requires editing then we include the editing prototype
            {
                // then the editing prototype
                xml.append("<!--- START OF edit" + c.getSimpleName() + " CODE SEGMENT USED FOR EDITING MODE -->\n");
                xml.append("<div class=\"hidden\" id=\"edit" + c.getSimpleName() + "\">\n\n");

                xml.append("<fieldset>\n");

                xml.append("<legend>Edit " + simplename + "</legend>\n");

                xml.append("<div class=\"fieldsetwrap\">\n");

                if (fields.contains("byte[]")) {
                    xml.append("\n<form class=\"webform\" id=\"update" + c.getSimpleName().toLowerCase()
                            + "\" name=\"update" + c.getSimpleName().toLowerCase()
                            + "\" method=\"post\" enctype=\"multipart/form-data\" action=\"update"
                            + c.getSimpleName() + ".igx?id={../@id}\">\n");
                    xml.append("<input name=\"id\" type=\"hidden\" value=\"{../@id}\"/>\n");
                } else {
                    xml.append("\n<form class=\"webform\" id=\"update" + c.getSimpleName().toLowerCase()
                            + "\" name=\"update" + c.getSimpleName().toLowerCase()
                            + "\" method=\"post\" action=\"update" + c.getSimpleName() + ".igx?id={../@id}\">\n");
                }

                xml.append("     <div class=\"datafieldwrap\">\n");
                xml.append("     <table class=\"datafield\">\n");

                it = fields.keys();

                if (ce != null) {
                    Map cef = ce.getFields();

                    Iterator itr = cef.values().iterator();
                    while (itr.hasNext()) {
                        ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();

                        if (cfi.visible && _types.indexOf(cfi.type) > -1) {
                            if (!cfi.editable || !cfi.addable) {
                                xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                        + ":</td><td class=\"data full\"><pre><xsl:value-of select=\""
                                        + cfi.name.toLowerCase() + "\"/></pre></td></tr>\n");
                            } else {
                                if (cfi.type.equalsIgnoreCase("boolean")) {
                                    xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\">\n");
                                    xml.append("               <select id=\"select" + cfi.name + "\" name=\""
                                            + cfi.name.toLowerCase() + "\">\n");
                                    xml.append("                    <option selected=\"\"><xsl:value-of select=\""
                                            + cfi.name.toLowerCase() + "\"/></option>\n");
                                    xml.append("                    <option>true</option><option>false</option>\n");
                                    xml.append("               </select>");
                                    xml.append("          </td></tr>\n");
                                } else if (cfi.type.equalsIgnoreCase("byte[]") || cfi.type.equalsIgnoreCase("file")
                                        || cfi.type.equalsIgnoreCase("base64Binary")) {
                                    xml.append(" <xsl:choose>\n");
                                    xml.append("    <xsl:when test=\"normalize-space(" + cfi.name.toLowerCase()
                                            + ")\">\n");
                                    xml.append("           <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\"><input id=\"file" + cfi.name
                                            + "\" type=\"file\" name=\"" + cfi.name.toLowerCase()
                                            + "\"/><a href=\"get" + cfi.name + "In" + c.getSimpleName()
                                            + ".igx?id={../@id}\"><xsl:value-of select=\"" + cfi.name.toLowerCase()
                                            + "\"/></a> <a onClick=\"getConfirmation('Are you sure you want to remove {"
                                            + cfi.name.toLowerCase() + "}?','del" + cfi.name + "In"
                                            + c.getSimpleName()
                                            + ".igx?id={../@id}','')\" href=\"#\"><img src=\"images/trash.png\" alt=\"Trash\"/></a></td></tr>\n");
                                    xml.append("    </xsl:when>\n");
                                    xml.append("    <xsl:otherwise>\n");
                                    xml.append("           <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\"><input id=\"file" + cfi.name
                                            + "\" type=\"file\" name=\"" + cfi.name.toLowerCase()
                                            + "\"/></td></tr>\n");
                                    xml.append("    </xsl:otherwise>\n");
                                    xml.append(" </xsl:choose>\n");
                                } else if (cfi.type.equalsIgnoreCase("date")) {
                                    xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\"><input class=\"txtdtt\" id=\"calendar"
                                            + cfi.name + "\" type=\"text\" name=\"" + cfi.name.toLowerCase()
                                            + "\"  value=\"{" + cfi.name.toLowerCase()
                                            + "}\"/><a href=\"javascript:NewCssCal('calendar" + cfi.name
                                            + "','yyyymmdd','arrow',false,24,true)\"><img src=\"images/cal.gif\" width=\"16\" height=\"16\" alt=\"Pick a date\"/></a></td></tr>\n");
                                } else if (cfi.type.equalsIgnoreCase("dateTime")) {
                                    xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\"><input class=\"txtdtt\" id=\"calendar"
                                            + cfi.name + "\" type=\"text\" name=\"" + cfi.name.toLowerCase()
                                            + "\"  value=\"{" + cfi.name.toLowerCase()
                                            + "}\"/><a href=\"javascript:NewCssCal('calendar" + cfi.name
                                            + "','yyyymmdd','arrow',true,24,false)\"><img src=\"images/cal.gif\" width=\"16\" height=\"16\" alt=\"Pick a date\"/></a></td></tr>\n");
                                } else if (cfi.type.equalsIgnoreCase("select")) {

                                    String options = null;

                                    // first we check if the choices is a dynamic one
                                    if (cfi.choices.indexOf("Type.") > -1) {
                                        String optionname = null;
                                        String idfield = null;
                                        if (cfi.choices.split("=").length > 1) {
                                            optionname = cfi.choices.split("=")[0] + cfi.choices.split("=")[1];
                                            idfield = cfi.choices.split("=")[0];
                                            options = "                  <option value=\"{" + cfi.name.toLowerCase()
                                                    + "}\" selected=\"\">{%dyn_get"
                                                    + cfi.choices.substring(0, cfi.choices.indexOf("."))
                                                    + optionname + ".igx?id=<xsl:value-of select=\""
                                                    + cfi.name.toLowerCase() + "\"/>%}</option>\n";
                                        } else {
                                            optionname = cfi.choices.substring(cfi.choices.indexOf(".") + 1);
                                            options = "                  <option value=\"{" + cfi.name.toLowerCase()
                                                    + "}\" selected=\"\"><xsl:value-of select=\""
                                                    + cfi.name.toLowerCase() + "\"/></option>\n";
                                        }

                                        //options = options+"<%dyn_get"+cfi.choices.substring(0,cfi.choices.indexOf("."))+cfi.choices.substring(cfi.choices.indexOf(".")+1)+".igx%>";
                                        options = options + "                  <%dyn_"
                                                + cfi.choices.substring(0, cfi.choices.indexOf(".")) + optionname
                                                + "Select.igx%>\n    ";
                                    } else {
                                        options = "                  <option selected=\"\"><xsl:value-of select=\""
                                                + cfi.name.toLowerCase() + "\"/></option>\n";
                                        String[] choices = cfi.choices.split(",");
                                        if (choices != null && choices.length > 0) {
                                            for (int i = 0; i < choices.length; i++) {
                                                options = options + "                  <option>" + choices[i]
                                                        + "</option>\n";
                                            }
                                        } else {
                                            options = "                  <option selected=\"\">Active</option>\n                  <option>Suspended</option>\n";
                                        }

                                    }

                                    xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\">\n");
                                    xml.append("              <select id=\"select" + cfi.name + "\" name=\""
                                            + cfi.name.toLowerCase() + "\">\n" + options);
                                    xml.append("              </select>\n");
                                    xml.append("          </td></tr>\n");

                                } else if (cfi.type.equalsIgnoreCase("textarea")) {
                                    xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                            + ":</td><td class=\"data full\"><textarea class=\"ta\" id=\"textarea"
                                            + cfi.name + "\" name=\"" + cfi.name.toLowerCase() + "\" rows=\""
                                            + cfi.rows + "\" cols=\"" + cfi.columns + "\"><xsl:value-of select=\""
                                            + cfi.name.toLowerCase() + "\"/></textarea></td></tr>\n");
                                } else {
                                    if (cfi.maxlength > 0) {
                                        xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                                + ":</td><td class=\"data full\"><input class=\"txt\" id=\"text"
                                                + cfi.name + "\" name=\"" + cfi.name.toLowerCase()
                                                + "\" type=\"text\" value=\"{" + cfi.name.toLowerCase()
                                                + "}\" style=\"width: " + (cfi.maxlength * 10)
                                                + "px;\" maxlength=\"" + cfi.maxlength + "\"/></td></tr>\n");
                                    } else {
                                        xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                                + ":</td><td class=\"data full\"><input class=\"txt\" id=\"text"
                                                + cfi.name + "\" name=\"" + cfi.name.toLowerCase()
                                                + "\" type=\"text\" value=\"{" + cfi.name.toLowerCase()
                                                + "}\"/></td></tr>\n");
                                    }
                                }

                            }

                        }
                    }
                } else {
                    while (it.hasMoreElements()) {
                        String f = (String) it.nextElement();
                        String t = (String) fields.get(f);

                        if (t.equalsIgnoreCase("boolean")) {
                            xml.append("          <tr><td class=\"lbl\">" + f
                                    + ":</td><td class=\"data full\"><SELECT id=\"select" + f + "\" name=\""
                                    + f.toLowerCase() + "\">\n<OPTION SELECTED=\"\"><xsl:value-of select=\""
                                    + f.toLowerCase()
                                    + "\"/></OPTION>\n<OPTION>true</OPTION>\n<OPTION>false</OPTION>\n</SELECT></td></tr>\n");
                        } else if (t.equalsIgnoreCase("byte[]") || t.equalsIgnoreCase("file")) {
                            xml.append(" <xsl:choose>\n");
                            xml.append("    <xsl:when test=\"" + f.toLowerCase() + "=''\">\n");
                            xml.append("           <tr><td class=\"lbl\">" + f
                                    + ":</td><td class=\"data full\"><input id=\"file" + f
                                    + "\" type=\"file\" name=\"" + f.toLowerCase() + "\"/></td></tr>\n");
                            xml.append("    </xsl:when>\n");
                            xml.append("    <xsl:otherwise>\n");
                            xml.append("           <tr><td class=\"lbl\">" + f
                                    + ":</td><td class=\"data full\"><a href=\"get" + f + "In" + c.getSimpleName()
                                    + ".igx?id={../@id}\"><xsl:value-of select=\"" + f.toLowerCase()
                                    + "\"/></a>(<a href=\"remove" + f + "In" + c.getSimpleName()
                                    + ".igx?id={../@id}\">Remove</a>)<input id=\"file" + f
                                    + "\" type=\"file\" name=\"" + f.toLowerCase() + "\"/></td></tr>\n");
                            xml.append("    </xsl:otherwise>\n");
                            xml.append(" </xsl:choose>\n");

                        } else if (t.equalsIgnoreCase("XMLGregorianCalendar")) {
                            xml.append("          <tr><td class=\"lbl\">" + f
                                    + ":</td><td class=\"data full\"><input class=\"txtdtt\" id=\"calendar" + f
                                    + "\" type=\"text\" name=\"" + f.toLowerCase() + "\"  value=\"{"
                                    + f.toLowerCase() + "}\"/><a href=\"javascript:NewCssCal('calendar" + f
                                    + "','yyyymmdd','arrow',false,24,true)\"><img src=\"images/cal.gif\" width=\"16\" height=\"16\" alt=\"Pick a date\"/></a></td></tr>\n");
                        } else {
                            if (_textfields.indexOf(f.toLowerCase()) > -1) {
                                xml.append("          <tr><td class=\"lbl\">" + f
                                        + ":</td><td class=\"data full\"><textarea class=\"ta\" id=\"textarea" + f
                                        + "\" name=\"" + f.toLowerCase()
                                        + "\" rows=\"5\" cols=\"65\"><xsl:value-of select=\"" + f.toLowerCase()
                                        + "\"/></textarea></td></tr>\n");
                            } else {
                                if (f.equalsIgnoreCase("status")) {
                                    xml.append("          <tr><td class=\"lbl\">" + f
                                            + ":</td><td class=\"data full\"><SELECT id=\"select" + f + "\" name=\""
                                            + f.toLowerCase() + "\">\n<OPTION SELECTED=\"\"><xsl:value-of select=\""
                                            + f.toLowerCase()
                                            + "\"/></OPTION>\n<OPTION>Active</OPTION>\n<OPTION>Suspended</OPTION>\n</SELECT></td></tr>\n");
                                } else {

                                    xml.append("          <tr><td class=\"lbl\">" + f
                                            + ":</td><td class=\"data full\"><input class=\"txt\" id=\"text" + f
                                            + "\" name=\"" + f.toLowerCase() + "\" type=\"text\" value=\"{"
                                            + f.toLowerCase() + "}\"/></td></tr>\n");
                                }

                            }

                        }

                    }
                }

                xml.append("     </table>\n");
                xml.append("     </div>\n\n");
                xml.append(
                        "<input type=\"button\" value=\"Update\" onClick=\"javascript:buttonchangecontent('update"
                                + c.getSimpleName() + ".igx?id={../@id}','update" + c.getSimpleName().toLowerCase()
                                + "','contentdyn')\"/>\n");
                xml.append("</form>\n");
                xml.append("<div class=\"clear\"></div>\n");
                xml.append("</div>\n\n");
                xml.append("</fieldset>\n\n");

                xml.append("<div class=\"btnrow\">\n");
                //xml.append("     <form class=\"inlineform\" method=\"post\" action=\"edit"+c.getSimpleName()+".igx?id={../@id}\">\n");
                xml.append("     <form class=\"inlineform\">\n");
                xml.append(
                        "          <input type=\"button\" value=\"Delete\" onClick=\"getConfirmation('Are You Sure You Want to Delete this Record?','delete"
                                + c.getSimpleName() + ".igx?id={../@id}','')\"/>\n");
                xml.append("     </form>\n");
                xml.append("     <form class=\"inlineform\">\n");
                xml.append("          <input type=\"button\" value=\"Cancel\" onClick=\"hidedivDisplay('edit"
                        + c.getSimpleName() + "');showdivDisplay('view" + c.getSimpleName() + "');\"/>\n");
                xml.append("     </form>\n");
                xml.append("</div>\n\n");
                xml.append("</div>\n");
                xml.append("<div class=\"clear\"></div>\n");
                xml.append("<!--- END OF edit" + c.getSimpleName() + " CODE SEGMENT -->\n\n");

            }

            xml.append("<!--- START OF print" + c.getSimpleName()
                    + " LIST SEGMENT USED FOR POP-UP PRINTER FRIENDLY OUTPUT -->\n");
            xml.append("<div class=\"hidden\" id=\"printlist" + c.getSimpleName() + "\">\n\n");

            // then we get the complex types!
            for (int i = 0; i < m.length; i++) {
                name = m[i].getName();
                retval = m[i].getReturnType().getName();

                // what if this is a list?
                if (retval.endsWith("List")) {
                    String getter = m[i].getName();
                    Method met = c.getMethod(getter, (Class[]) null);
                    ParameterizedType t = (ParameterizedType) met.getGenericReturnType();
                    Class c1 = (Class) t.getActualTypeArguments()[0];
                    String childname = m[i].getName().substring(3);

                    childname = childname.substring(0, 1).toUpperCase() + childname.substring(1);

                    String clsname = indexable(c1.getSimpleName()) ? "Flex" + c1.getSimpleName()
                            : c1.getSimpleName();

                    xml.append("     <!--- START OF print" + childname + " LIST CODE SEGMENT -->\n");
                    xml.append("     <div id=\"print" + childname + "\">\n");
                    xml.append("     <fieldset>\n");
                    xml.append("     <legend>" + childname + " List</legend>\n");
                    xml.append("     <div class=\"fieldsetwrap\">\n");
                    xml.append("     <table class=\"sortable\">\n");

                    ConfigElement ce2 = config.getElementConfig(c1.getSimpleName());
                    Map cef = ce2.getFields();

                    Iterator itr = cef.values().iterator();
                    xml.append("          <thead><tr>\n");
                    String sortfield = null;
                    while (itr.hasNext()) {
                        ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                        if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                            xml.append("               <th>" + cfi.label + "</th>\n");
                            if (sortfield == null) {
                                sortfield = cfi.name.toLowerCase();
                            }
                        }
                    }
                    xml.append("          </tr></thead>\n");

                    xml.append("          <xsl:for-each select=\"" + c1.getSimpleName().toLowerCase() + "\">\n");
                    xml.append("          <xsl:sort select=\"" + sortfield + "\" order=\"descending\"/>\n");

                    xml.append("          <tr>\n");
                    itr = cef.values().iterator();
                    while (itr.hasNext()) {
                        ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                        if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                            if (cfi.type.equals("byte[]")) {
                                xml.append("               <td><xsl:value-of select=\"" + cfi.name.toLowerCase()
                                        + "\"/></td>\n");
                            } else {
                                if (cfi.type.equalsIgnoreCase("decimal")) {
                                    xml.append("               <td><xsl:value-of select=\"format-number("
                                            + cfi.name.toLowerCase() + ",'###,###,##0.00')\"/></td>\n");
                                } else {
                                    xml.append("               <td><pre><xsl:value-of select=\""
                                            + cfi.name.toLowerCase() + "\"/></pre></td>\n");
                                }
                            }
                        }

                    }
                    xml.append("          </tr>\n");
                    xml.append("          </xsl:for-each>\n");

                    xml.append("     </table>\n");

                    xml.append("     <div class=\"clear\"></div>\n");
                    xml.append("     </div>\n\n");
                    xml.append("     </fieldset>\n");
                    xml.append("     </div>\n");
                    xml.append("     <!--- END OF print" + childname + " LIST CODE SEGMENT -->\n\n");
                } else {
                    if ("int,boolean".indexOf(retval) < 0 && !retval.startsWith("java") && !retval.equals("void")
                            && !retval.equals("[B")) {
                        String getter = m[i].getName();
                        Method met = c.getMethod(getter, (Class[]) null);
                        Class c1 = (Class) met.getGenericReturnType();
                        String childname = m[i].getName().substring(3);

                        childname = childname.substring(0, 1).toUpperCase() + childname.substring(1);

                        String clsname = indexable(c1.getSimpleName()) ? "Flex" + c1.getSimpleName()
                                : c1.getSimpleName();

                        xml.append("     <!--- START OF print" + childname + " CHILD CODE SEGMENT -->\n");
                        xml.append("     <div id=\"print" + childname + "\">\n");
                        xml.append("     <fieldset>\n");
                        xml.append("     <legend>" + childname + "</legend>\n");
                        xml.append("     <div class=\"fieldsetwrap\">\n");
                        xml.append("     <table class=\"sortable\">\n");

                        ConfigElement ce2 = config.getElementConfig(c1.getSimpleName());
                        Map cef = ce2.getFields();

                        Iterator itr = cef.values().iterator();
                        xml.append("          <thead><tr>\n");
                        String sortfield = null;
                        while (itr.hasNext()) {
                            ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                            if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                                xml.append("               <th>" + cfi.label + "</th>\n");
                                if (sortfield == null) {
                                    sortfield = cfi.name.toLowerCase();
                                }
                            }
                        }
                        xml.append("          </tr></thead>\n");

                        xml.append(
                                "          <xsl:for-each select=\"" + c1.getSimpleName().toLowerCase() + "\">\n");
                        xml.append("          <xsl:sort select=\"" + sortfield + "\" order=\"descending\"/>\n");

                        xml.append("          <tr>\n");
                        itr = cef.values().iterator();
                        while (itr.hasNext()) {
                            ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                            if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                                if (cfi.type.equals("byte[]") || cfi.type.equals("base64Binary")) {
                                    xml.append("               <td><xsl:value-of select=\"" + cfi.name.toLowerCase()
                                            + "\"/></td>\n");
                                } else {
                                    if (cfi.type.equalsIgnoreCase("decimal")) {
                                        xml.append("               <td><xsl:value-of select=\"format-number("
                                                + cfi.name.toLowerCase() + ",'###,###,##0.00')\"/></td>\n");
                                    } else {
                                        xml.append("               <td><pre><xsl:value-of select=\""
                                                + cfi.name.toLowerCase() + "\"/></pre></td>\n");
                                    }

                                    //xml.append("               <td><xsl:value-of select=\""+cfi.name.toLowerCase()+"\"/></td>\n");
                                }
                            }

                        }
                        xml.append("          </tr>\n");
                        xml.append("          </xsl:for-each>\n");
                        xml.append("     </table>\n\n");

                        //xml.append("     </xsl:if>\n");
                        xml.append("     <div class=\"clear\"></div>\n");
                        xml.append("     </div>\n");
                        xml.append("     </fieldset>\n");
                        xml.append("     </div>\n");
                        xml.append("     <!--- END OF print" + childname + " CHILD CODE SEGMENT -->\n\n");
                    }
                }
            }
            xml.append("</div>\n");
            xml.append("<!--- END OF print" + c.getSimpleName() + " LIST SEGMENT -->\n\n");

            // as well as the print friendly version
            xml.append("<!--- START OF print" + c.getSimpleName() + " CODE SEGMENT -->\n");
            xml.append("<div class=\"hidden\" id=\"print" + c.getSimpleName() + "\">\n");
            xml.append("<!--- dont show the printing and editing divs  -->\n");
            xml.append(
                    "<script language=\"JavaScript\">hidedivDisplay('edit" + c.getSimpleName() + "');</script>\n");
            xml.append(
                    "<script language=\"JavaScript\">hidedivDisplay('print" + c.getSimpleName() + "');</script>\n");
            xml.append("<script language=\"JavaScript\">hidedivDisplay('printlist" + c.getSimpleName()
                    + "');</script>\n");

            xml.append("<fieldset>\n");

            xml.append("<legend>View " + c.getSimpleName().substring(0, c.getSimpleName().length() - 4)
                    + "</legend>\n");

            xml.append("<div class=\"fieldsetwrap\">\n");

            xml.append("     <div class=\"datafieldwrap\">\n");
            xml.append("     <table class=\"datafield\">\n");

            if (ce != null) {
                Map cef = ce.getFields();
                Iterator itr = cef.values().iterator();
                while (itr.hasNext()) {
                    ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                    if (cfi.visible && _types.indexOf(cfi.type) > -1) {
                        if (cfi.type.equalsIgnoreCase("decimal")) {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"><xsl:value-of select=\"format-number("
                                    + cfi.name.toLowerCase() + ",'###,###,##0.00')\"/></td></tr>\n");
                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"><pre><xsl:value-of select=\""
                                    + cfi.name.toLowerCase() + "\"/></pre></td></tr>\n");
                        }
                        //xml.append("               <th>"+cfi.label+"</th>\n");
                    }
                }
            } else {
                it = fields.keys();

                while (it.hasMoreElements()) {
                    String f = (String) it.nextElement();
                    String t = (String) fields.get(f);
                    if (t.equalsIgnoreCase("decimal")) {
                        xml.append("          <tr><td class=\"lbl\">" + f
                                + ":</td><td class=\"data full\"><xsl:value-of select=\"format-number("
                                + f.toLowerCase() + ",'###,###,##0.00')\"/></td></tr>\n");
                    } else {
                        xml.append("          <tr><td class=\"lbl\">" + f
                                + ":</td><td class=\"data full\"><pre><xsl:value-of select=\"" + f.toLowerCase()
                                + "\"/></pre></td></tr>\n");
                    }
                }
            }

            xml.append("     </table>\n");
            xml.append("     </div>\n");
            xml.append("</div>\n");
            xml.append("</fieldset>\n");
            xml.append("</div>\n");
            xml.append("<div class=\"clear\"></div>\n");
            xml.append("<!--- END OF print" + c.getSimpleName() + " CODE SEGMENT -->\n\n");

            // if this is a prototype for an empty record
            if (type == 2) {
                System.out.println("NO PROTOTYPE FOR " + c.getSimpleName());
            }

            xml.append("<!--- START OF " + c.getSimpleName() + " LIST SEGMENT -->\n");
            xml.append("<div id=\"list" + c.getSimpleName() + "\">\n\n");

            // then we get the complex types!
            for (int i = 0; i < m.length; i++) {
                name = m[i].getName();
                retval = m[i].getReturnType().getName();

                // what if this is a list?
                if (retval.endsWith("List")) {
                    String getter = m[i].getName();
                    Method met = c.getMethod(getter, (Class[]) null);
                    ParameterizedType t = (ParameterizedType) met.getGenericReturnType();
                    Class c1 = (Class) t.getActualTypeArguments()[0];
                    String childname = m[i].getName().substring(3);

                    childname = childname.substring(0, 1).toUpperCase() + childname.substring(1);

                    String clsname = indexable(c1.getSimpleName()) ? "Flex" + c1.getSimpleName()
                            : c1.getSimpleName();

                    xml.append("     <!--- START OF " + childname + " LIST CODE SEGMENT -->\n");
                    xml.append("     <div id=\"child" + childname + "\">\n");
                    xml.append("     <fieldset>\n");
                    xml.append("     <legend>" + childname + " List</legend>\n");
                    xml.append("     <div class=\"fieldsetwrap\">\n");
                    xml.append("     <div style=\"overflow:auto; height:200px;\">\n");
                    xml.append("     <table class=\"sortable\">\n");

                    ConfigElement ce2 = config.getElementConfig(c1.getSimpleName());
                    Map cef = ce2.getFields();

                    Iterator itr = cef.values().iterator();
                    xml.append("          <thead><tr>\n");
                    String sortfield = null;
                    while (itr.hasNext()) {
                        ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                        if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                            xml.append("               <th>" + cfi.label + "</th>\n");
                            if (sortfield == null) {
                                sortfield = cfi.name.toLowerCase(); // by default the first column
                            }
                        }
                    }
                    xml.append("          </tr></thead>\n");

                    xml.append("          <xsl:for-each select=\"" + c1.getSimpleName().toLowerCase() + "\">\n");
                    xml.append("          <xsl:sort select=\"" + sortfield + "\" order=\"descending\"/>\n");

                    xml.append("          <tr>\n");
                    itr = cef.values().iterator();
                    while (itr.hasNext()) {
                        ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                        if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                            if (cfi.type.equals("byte[]") || cfi.type.equals("base64Binary")) {
                                xml.append("               <td><xsl:value-of select=\"" + cfi.name.toLowerCase()
                                        + "\"/></td>\n");
                            } else {
                                if (cfi.type.equalsIgnoreCase("decimal")) {
                                    xml.append("               <td><xsl:value-of select=\"format-number("
                                            + cfi.name.toLowerCase() + ",'###,###,##0.00')\"/></td>\n");
                                } else {
                                    xml.append("               <td><pre><xsl:value-of select=\""
                                            + cfi.name.toLowerCase() + "\"/></pre></td>\n");
                                }
                            }
                        }

                    }

                    /*Hashtable v = getFields(c1.newInstance());
                    Enumeration it2 = v.keys();
                        
                    xml.append("          <thead><tr>\n");
                    while (it2.hasMoreElements())
                    {
                    String f2 = (String) it2.nextElement();
                    xml.append("               <th>"+f2+"</th>\n");
                    }
                    xml.append("          </tr></thead>\n");
                        
                    it2 = v.keys();
                        
                    xml.append("          <xsl:for-each select=\""+childname+"\">\n");
                    xml.append("          <tr>\n");
                    while (it2.hasMoreElements())
                    {
                    String f2 = (String) it2.nextElement();
                    String t2 = (String) v.get(f2);
                        
                    if (t2.equals("byte[]"))
                    {
                        xml.append("               <td><xsl:value-of select=\""+f2+"\"/></td>\n");
                    }
                    else
                    {
                        xml.append("               <td><xsl:value-of select=\""+f2+"\"/></td>\n");
                    }
                        
                    }
                    */
                    xml.append("          </tr>\n");
                    xml.append("          </xsl:for-each>\n");

                    xml.append("     </table>\n");
                    xml.append("     </div>\n");

                    xml.append("     <div id=\"list" + childname + "buttons\">\n\n");
                    xml.append("       <input type=\"button\" value=\"View " + childname + " List\"   onClick=\""
                            + (message != null ? "hidedivDisplay('message');" : "")
                            + "javascript:linkchangecontent('get" + clsname
                            + "WithParentID.igx?id={../@id}&amp;do=savecontext&amp;"
                            + c1.getSimpleName().toLowerCase() + "parent=get" + c.getSimpleName() + ".igx&amp;"
                            + c1.getSimpleName().toLowerCase() + "parentname="
                            + c.getSimpleName().substring(0, c.getSimpleName().length() - 4) + "&amp;"
                            + c1.getSimpleName().toLowerCase()
                            + "parentid=<%var_request[id]%>&amp;from=0&amp;to=15','contentdyn')\"/>\n");
                    xml.append("       <input type=\"button\" value=\"New " + childname + "\"   onClick=\""
                            + (message != null ? "hidedivDisplay('message');" : "")
                            + "javascript:linkchangecontent('new" + clsname
                            + ".htm?id={../@id}&amp;do=savecontext&amp;" + c1.getSimpleName().toLowerCase()
                            + "parent=get" + c.getSimpleName() + ".igx&amp;" + c1.getSimpleName().toLowerCase()
                            + "parentname=" + c.getSimpleName().substring(0, c.getSimpleName().length() - 4)
                            + "&amp;" + c1.getSimpleName().toLowerCase()
                            + "parentid=<%var_request[id]%>','contentdyn')\"/>\n");
                    xml.append("     </div>\n\n");

                    xml.append("     <div class=\"clear\"></div>\n");
                    xml.append("     </div>\n\n");
                    xml.append("     </fieldset>\n");
                    xml.append("     </div>\n");
                    xml.append("     <!--- END OF " + childname + " LIST CODE SEGMENT -->\n\n");
                } else {
                    if ("int,boolean".indexOf(retval) < 0 && !retval.startsWith("java") && !retval.equals("void")
                            && !retval.equals("[B")) {
                        String getter = m[i].getName();
                        Method met = c.getMethod(getter, (Class[]) null);
                        Class c1 = (Class) met.getGenericReturnType();
                        String childname = m[i].getName().substring(3);

                        childname = childname.substring(0, 1).toUpperCase() + childname.substring(1);

                        String clsname = indexable(c1.getSimpleName()) ? "Flex" + c1.getSimpleName()
                                : c1.getSimpleName();

                        xml.append("     <!--- START OF SINGLETON " + childname + " CHILD CODE SEGMENT -->\n");
                        xml.append("     <div id=\"child" + c.getSimpleName() + "\">\n");
                        xml.append("     <fieldset>\n");
                        xml.append("     <legend>" + childname + "</legend>\n");
                        xml.append("     <div class=\"fieldsetwrap\">\n");
                        xml.append("     <div style=\"overflow:auto; height:200px;\">\n");
                        xml.append("     <table class=\"sortable\">\n");

                        ConfigElement ce2 = config.getElementConfig(c1.getSimpleName());
                        Map cef = ce2.getFields();

                        Iterator itr = cef.values().iterator();
                        xml.append("          <thead><tr>\n");

                        String sortfield = null;

                        while (itr.hasNext()) {
                            ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                            if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                                xml.append("               <th>" + cfi.label + "</th>\n");

                                if (sortfield == null) {
                                    sortfield = cfi.name.toLowerCase();
                                }
                            }
                        }
                        xml.append("          </tr></thead>\n");

                        xml.append(
                                "          <xsl:for-each select=\"" + c1.getSimpleName().toLowerCase() + "\">\n");
                        xml.append("          <xsl:sort select=\"" + sortfield + "\" order=\"descending\"/>\n");
                        xml.append("          <tr>\n");
                        itr = cef.values().iterator();
                        while (itr.hasNext()) {
                            ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();
                            if (cfi.visible && cfi.showinlist && _types.indexOf(cfi.type) > -1) {
                                if (cfi.type.equals("byte[]") || cfi.type.equals("base64Binary")) {
                                    xml.append("               <td><xsl:value-of select=\"" + cfi.name.toLowerCase()
                                            + "\"/></td>\n");
                                } else {
                                    if (cfi.type.equalsIgnoreCase("decimal")) {
                                        xml.append("               <td><xsl:value-of select=\"format-number("
                                                + cfi.name.toLowerCase() + ",'###,###,##0.00')\"/></td>\n");
                                    } else {
                                        xml.append("               <td><pre><xsl:value-of select=\""
                                                + cfi.name.toLowerCase() + "\"/></pre></td>\n");
                                    }

                                }
                            }

                        }
                        /*Hashtable v = getFields(c1.newInstance());
                        Enumeration it2 = v.keys();
                            
                        xml.append("          <thead><tr>\n");
                        while (it2.hasMoreElements())
                        {
                        String f2 = (String) it2.nextElement();
                        xml.append("               <th>"+f2+"</th>\n");
                        }
                        xml.append("          </tr></thead>\n");
                            
                        it2 = v.keys();
                            
                        xml.append("          <xsl:for-each select=\""+childname+"\">\n");
                        xml.append("          <tr>\n");
                        while (it2.hasMoreElements())
                        {
                        String f2 = (String) it2.nextElement();
                        String t2 = (String) v.get(f2);
                            
                        if (t2.equals("byte[]"))
                        {
                            xml.append("               <td><xsl:value-of select=\""+f2+"\"/></td>\n");
                        }
                        else
                        {
                            xml.append("               <td><xsl:value-of select=\""+f2+"\"/></td>\n");
                        }
                            
                        }
                        */
                        xml.append("          </tr>\n");
                        xml.append("          </xsl:for-each>\n");
                        xml.append("     </table>\n");
                        xml.append("     </div>\n\n");

                        xml.append("     <div id=\"list" + childname + "buttons\">\n\n");
                        xml.append("       <input type=\"button\" value=\"View " + childname + "\"   onClick=\""
                                + (message != null ? "hidedivDisplay('message');" : "")
                                + "javascript:linkchangecontent('get" + clsname
                                + "WithParentID.igx?id={../@id}&amp;do=savecontext&amp;"
                                + c1.getSimpleName().toLowerCase() + "parent=get" + c.getSimpleName() + ".igx&amp;"
                                + c1.getSimpleName().toLowerCase() + "parentname=" + c.getSimpleName() + "&amp;"
                                + c1.getSimpleName().toLowerCase()
                                + "parentid=<%var_request[id]%>','contentdyn')\"/>\n");
                        xml.append("       <input type=\"button\" value=\"Create " + childname + "\"   onClick=\""
                                + (message != null ? "hidedivDisplay('message');" : "")
                                + "javascript:linkchangecontent('new" + clsname
                                + ".htm?id={../@id}','contentdyn')\"/>\n");
                        xml.append("     </div>\n\n");

                        xml.append("     <div class=\"clear\"></div>\n");
                        xml.append("     </div>\n");
                        xml.append("     </fieldset>\n");
                        xml.append("     </div>\n");
                        xml.append("     <!--- END OF SINGLETON " + childname + " CHILD CODE SEGMENT -->\n\n");
                    }
                }
            }

            xml.append("</div>\n");
            xml.append("<!--- END OF " + c.getSimpleName() + " LIST SEGMENT -->\n\n");

            xml.append("</xsl:template>\n\n");

        }

        return xml.toString();

    }

    /**
    * obtains an HTML OPTIONS XSL prototype for the given object and field.
    *
    * @param  obj the object containing the elements that will be used to populate the XSL.
    * @param  valuefield the field name to retrieve.
    * @param  descriptionfield the field description to retrieve.
     * @return XSL string.
    * @see Hashtable
     *@see Element
    */
    public String getOptionsXSLPrototype(Object obj, String idfield, String valuefield, String descriptionfield)
            throws Exception {
        Class c = obj.getClass();
        StringBuffer xml = new StringBuffer();

        xml.append("\n<xsl:template match=\"LIST\">\n");
        xml.append("    <xsl:apply-templates select=\"flexcontainer/" + c.getSimpleName().toLowerCase() + "\"/>\n");
        xml.append("</xsl:template>\n");
        xml.append("<xsl:template match=\"flexcontainer/" + c.getSimpleName().toLowerCase() + "\">\n");
        xml.append("    <xsl:for-each select=\".\">\n");
        if (descriptionfield == null || valuefield.equalsIgnoreCase(descriptionfield)) {
            descriptionfield = valuefield;
        }
        if (!valuefield.equalsIgnoreCase(idfield)) {
            xml.append("        <option value=\"{../@" + (idfield != null ? idfield : valuefield)
                    + "}\"><xsl:value-of select=\"" + valuefield + "\"/></option>\n");
        } else {
            xml.append("        <option value=\"{" + (idfield != null ? idfield : valuefield)
                    + "}\"><xsl:value-of select=\"" + valuefield + "\"/></option>\n");
        }
        xml.append("    </xsl:for-each>\n");
        xml.append("</xsl:template>\n");

        return xml.toString();

    }

    /**
    * obtains an HTML OPTIONS XSL prototype for the given object and field.
    *
    * @param  obj the object containing the elements that will be used to populate the XSL.
    * @param  fieldname the field description to retrieve.
    * @return XSL string.
    * @see Hashtable
    *@see Element
    */
    public String getSimpleNameXSLPrototype(Object obj, String fieldname) throws Exception {
        Class c = obj.getClass();
        StringBuffer xml = new StringBuffer();

        xml.append("<xsl:template match=\"flexcontainer\">\n");
        xml.append("  <xsl:for-each select=\"" + c.getSimpleName().toLowerCase() + "\">\n");
        xml.append("      <xsl:value-of select=\"" + fieldname + "\"/>\n");
        xml.append("  </xsl:for-each>\n");
        xml.append("</xsl:template>\n");

        return xml.toString();

    }

    /**
    * obtains an HTML Input Form prototype for the object.
    *
    * @param  title optional title in the XSL prorotype, can be null (ie none).
    * @param  obj optional UI configuration.
    * @param  obj the object containing the elements that will be used to populate the XSL.
    * @return XSL string.
    * @see Hashtable
     *@see Element
    */
    public String getHTMLFormPrototype(String title, Config config, Object obj, String parentclass)
            throws Exception {
        Class c = obj.getClass();
        //Method[] m = c.getMethods();
        Vector ve = retrieveMethods(c, null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        StringBuffer xml = new StringBuffer();
        //xml.append("<"+c.getSimpleName()+">");
        Hashtable fields = getFields(obj);

        Enumeration it = fields.keys();

        if (parentclass != null) {
            xml.append("\n<div>\n<span style=\"font-size:14px;font-weight:bold\">\n");
            xml.append("    <a onClick=\"javascript:linkchangecontent('<%var_context[" + parentclass.toLowerCase()
                    + "parent]%>?id=<%var_context[" + parentclass.toLowerCase()
                    + "parentid]%>','contentdyn')\" href=\"#\">\n");
            xml.append("    <%var_context[" + parentclass.toLowerCase() + "parentname]%>\n");
            xml.append("    </a>\n");
            xml.append("</span>\n</div>\n\n");
        }

        if (title != null) {
            xml.append("          <fieldset>\n            <legend>" + title
                    + "</legend>\n            <div class=\"fieldsetwrap\">\n");
        } else {
            xml.append("          <fieldset>\n            <legend>New "
                    + c.getSimpleName().substring(0, c.getSimpleName().length() - 4)
                    + "</legend>\n            <div class=\"fieldsetwrap\">\n");
        }

        if (fields.contains("byte[]")) {
            xml.append("\n     <form class=\"webform\" id=\"" + c.getSimpleName().toLowerCase() + "\" name=\""
                    + c.getSimpleName().toLowerCase()
                    + "\" method=\"post\" enctype=\"multipart/form-data\" action=\"add" + c.getSimpleName()
                    + ".igx\">\n");
        } else {
            xml.append("\n     <form class=\"webform\" id=\"" + c.getSimpleName().toLowerCase() + "\" name=\""
                    + c.getSimpleName().toLowerCase() + "\" method=\"post\" action=\"add" + c.getSimpleName()
                    + ".igx\">\n");
        }
        xml.append("     <input name=\"id\" type=\"hidden\" value=\"<%var_request[id]%>\"/>\n");

        xml.append("     <div class=\"datafieldwrap\">\n");
        xml.append("      <table class=\"datafield\">\n");

        ConfigElement ce = config.getElementConfig(c.getSimpleName());
        // if we found a config for this then we generate it in order.
        if (ce != null) {
            Map cef = ce.getFields();

            Iterator itr = cef.values().iterator();
            while (itr.hasNext()) {
                ConfigFieldInfo cfi = (ConfigFieldInfo) itr.next();

                if (cfi.visible && _types.indexOf(cfi.type) > -1) {
                    if (cfi.type.equalsIgnoreCase("boolean")) {
                        if (cfi.addable) {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\">\n<SELECT id=\"select" + cfi.name
                                    + "\" name=\"" + cfi.name.toLowerCase()
                                    + "\">\n<OPTION SELECTED=\"\">true</OPTION>\n<OPTION>false</OPTION>\n</SELECT></td></tr>\n");
                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"></td></tr>\n");
                        }
                    } else if (cfi.type.equalsIgnoreCase("byte[]") || cfi.type.equalsIgnoreCase("file")) {
                        if (cfi.addable) {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\">\n<input id=\"file" + cfi.name
                                    + "\" type=\"file\" name=\"" + cfi.name.toLowerCase() + "\"/></td></tr>\n");
                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"></td></tr>\n");
                        }

                    } else if (cfi.type.equalsIgnoreCase("date")) {
                        if (cfi.addable) {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\">\n<input class=\"txtdtt\" id=\"calendar"
                                    + cfi.name + "\" type=\"text\" name=\"" + cfi.name.toLowerCase()
                                    + "\"/><a href=\"javascript:NewCssCal('calendar" + cfi.name
                                    + "','yyyymmdd','arrow',false,24,true)\"><img src=\"images/cal.gif\" width=\"16\" height=\"16\" alt=\"Pick a date\"/></a></td></tr>\n");
                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"></td></tr>\n");
                        }

                    } else if (cfi.type.equalsIgnoreCase("dateTime")) {
                        if (cfi.addable) {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\">\n<input class=\"txtdtt\" id=\"calendar"
                                    + cfi.name + "\" type=\"text\" name=\"" + cfi.name.toLowerCase()
                                    + "\"/><a href=\"javascript:NewCssCal('calendar" + cfi.name
                                    + "','yyyymmdd','arrow',true,24,false)\"><img src=\"images/cal.gif\" width=\"16\" height=\"16\" alt=\"Pick a date\"/></a></td></tr>\n");
                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"></td></tr>\n");
                        }
                    } else if (cfi.type.equalsIgnoreCase("select")) {
                        if (cfi.addable) {

                            String options = null;

                            // first we check if the choices is a dynamic one
                            if (cfi.choices.indexOf("Type.") > -1) {
                                String optionname = null;
                                String idfield = null;
                                if (cfi.choices.split("=").length > 1) {
                                    optionname = cfi.choices.split("=")[0] + cfi.choices.split("=")[1];
                                    idfield = cfi.choices.split("=")[0];
                                } else {
                                    optionname = cfi.choices;
                                }

                                options = "<%dyn_" + cfi.choices.substring(0, cfi.choices.indexOf("."))
                                        + cfi.choices.substring(cfi.choices.indexOf(".") + 1) + "Select.igx%>";

                            } else {
                                String[] choices = cfi.choices.split(",");
                                if (choices != null && choices.length > 0) {
                                    for (int i = 0; i < choices.length; i++) {
                                        if (i == 0) {
                                            options = "<OPTION SELECTED=\"\" value=\"" + choices[i] + "\">"
                                                    + choices[i] + "</OPTION>";
                                        } else {
                                            options = options + "<OPTION value=\"" + choices[i] + "\">" + choices[i]
                                                    + "</OPTION>";
                                        }
                                    }
                                } else {
                                    options = "<OPTION SELECTED=\"\" value=\"Active\">Active</OPTION>\n<OPTION value=\"Suspended\">Suspended</OPTION>";
                                }
                            }

                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\">\n<SELECT id=\"select" + cfi.name
                                    + "\" name=\"" + cfi.name.toLowerCase() + "\">\n" + options
                                    + "\n</SELECT></td></tr>\n");

                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"></td></tr>\n");
                        }
                    } else if (cfi.type.equalsIgnoreCase("textarea")) {
                        if (cfi.addable) {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"><textarea class=\"ta\" id=\"textarea"
                                    + cfi.name + "\" name=\"" + cfi.name.toLowerCase() + "\" rows=\"" + cfi.rows
                                    + "\" cols=\"" + cfi.columns + "\"></textarea></td></tr>\n");
                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                    + ":</td><td class=\"data full\"></td></tr>\n");
                        }

                    } else {
                        if (cfi.addable) {
                            if (cfi.maxlength > 0) {
                                xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                        + ":</td><td class=\"data full\"><input class=\"txt\" id=\"text" + cfi.name
                                        + "\" name=\"" + cfi.name.toLowerCase()
                                        + "\" type=\"text\" value=\"\" style=\"width: " + (cfi.maxlength * 10)
                                        + "px;\" maxlength=\"" + cfi.maxlength + "\"/></td></tr>\n");
                            } else {
                                xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                        + ":</td><td class=\"data full\"><input class=\"txt\" id=\"text" + cfi.name
                                        + "\" name=\"" + cfi.name.toLowerCase()
                                        + "\" type=\"text\" value=\"\"/></td></tr>\n");
                            }

                        } else {
                            if (cfi.maxlength > 0) {
                                xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                        + ":</td><td class=\"data full\"></td></tr>\n");
                            } else {
                                xml.append("          <tr><td class=\"lbl\">" + cfi.label
                                        + ":</td><td class=\"data full\"></td></tr>\n");
                            }
                        }
                    }
                }
            }
        } else {
            while (it.hasMoreElements()) {
                String f = (String) it.nextElement();
                String t = (String) fields.get(f);

                if (t.equalsIgnoreCase("boolean")) {
                    xml.append("          <tr><td class=\"lbl\">" + f
                            + ":</td><td class=\"data full\">\n<SELECT id=\"select" + f + "\" name=\""
                            + f.toLowerCase()
                            + "\">\n<OPTION SELECTED=\"\">true</OPTION>\n<OPTION>false</OPTION>\n</SELECT></td></tr>\n");
                } else if (t.equalsIgnoreCase("byte[]")) {
                    xml.append("          <tr><td class=\"lbl\">" + f
                            + ":</td><td class=\"data full\">\n<input id=\"file" + f + "\" type=\"file\" name=\""
                            + f.toLowerCase() + "\"/></td></tr>\n");
                } else if (t.equalsIgnoreCase("XMLGregorianCalendar")) {
                    xml.append("          <tr><td class=\"lbl\">" + f
                            + ":</td><td class=\"data full\">\n<input class=\"txtdtt\" id=\"calendar" + f
                            + "\" type=\"text\" name=\"" + f.toLowerCase()
                            + "\"/><a href=\"javascript:NewCssCal('calendar" + f
                            + "','yyyymmdd','arrow',false,24,true)\"><img src=\"images/cal.gif\" width=\"16\" height=\"16\" alt=\"Pick a date\"/></a></td></tr>\n");
                } else {
                    // generate text area for common text field names
                    if (_textfields.indexOf(f.toLowerCase()) > -1) {
                        xml.append("          <tr><td class=\"lbl\">" + f
                                + ":</td><td class=\"data full\"><textarea class=\"ta\" id=\"textarea" + f
                                + "\" name=\"" + f.toLowerCase()
                                + "\" rows=\"5\" cols=\"65\"></textarea></td></tr>\n");
                    } else {
                        // hard coded convenience
                        if (f.equalsIgnoreCase("status")) {
                            xml.append("          <tr><td class=\"lbl\">" + f
                                    + ":</td><td class=\"data full\">\n<SELECT id=\"select" + f + "\" name=\""
                                    + f.toLowerCase()
                                    + "\">\n<OPTION SELECTED=\"\">Active</OPTION>\n<OPTION>Suspended</OPTION>\n</SELECT></td></tr>\n");
                        } else {
                            xml.append("          <tr><td class=\"lbl\">" + f
                                    + ":</td><td class=\"data full\"><input class=\"txt\" id=\"text" + f
                                    + "\" name=\"" + f.toLowerCase() + "\" type=\"text\" value=\"\"/></td></tr>\n");
                        }
                    }
                }
            }
        }

        xml.append("      </table>\n");
        xml.append("     </div>\n");

        xml.append("          <input type=\"button\" value=\"Save\"  onClick=\"javascript:buttonchangecontent('add"
                + c.getSimpleName() + ".igx','" + c.getSimpleName().toLowerCase() + "','contentdyn')\"/>\n");
        xml.append("     </form>\n     <div class=\"clear\"></div>\n   </div>\n    </fieldset>\n");
        xml.append("      <table><tr>\n");
        xml.append("     <td>\n");
        xml.append("     <form class=\"inlineform\" id=\"list" + c.getSimpleName().toLowerCase() + "\" name=\"list"
                + c.getSimpleName().toLowerCase() + "\" method=\"post\" action=\"list" + c.getSimpleName()
                + ".igx\">\n");
        if (parentclass != null) {
            xml.append("     <input type=\"button\" onClick=\"javascript:linkchangecontent('<%var_context["
                    + parentclass.toLowerCase() + "parent]%>?id=<%var_context[" + parentclass.toLowerCase()
                    + "parentid]%>','contentdyn')\" value=\"Cancel\"/>\n");
        } else {
            xml.append("     <input type=\"button\" onClick=\"javascript:linkchangecontent('list"
                    + c.getSimpleName() + ".igx?from=0&amp;to=10','contentdyn')\" value=\"Cancel\"/>\n");

        }

        xml.append("     </form></td>\n");
        xml.append("      </tr></table>\n");

        //main.append("<"+c.getSimpleName()+" id=\""+id+"\" parentid=\""+parentid+"\">");
        return xml.toString();

    }

    static public Hashtable getFields(Object obj) {
        Hashtable<String, String> fields = new Hashtable<String, String>();

        //Method[] m = obj.getClass().getMethods();
        Vector ve = retrieveMethods(obj.getClass(), null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        String name, retval;
        String id = null;
        String parentid = null;
        StringBuffer xml = new StringBuffer();
        StringBuffer listheader = new StringBuffer();
        //xml.append("<"+c.getSimpleName()+">");

        for (int i = 0; i < m.length; i++) {
            name = m[i].getName();
            retval = m[i].getReturnType().getName();
            if (retval.equalsIgnoreCase("void") && name.startsWith("set")) {
                // we get the method name
                String field = name.substring(3);
                String getter = (((m[i].getParameterTypes()[0] + "").equals("boolean")) ? "is" : "get") + field;
                try {

                    Method met = obj.getClass().getMethod(getter, (Class[]) null);

                    Object o = null;
                    try {
                        o = met.invoke(obj, (Object[]) null);
                    } catch (Exception g) {
                    }

                    if (o != null) {
                        String t = met.getReturnType().getSimpleName();

                        if (indexable(t)) {
                            if (field.equals("Id")) {
                                id = o.toString();
                            } else if (field.equals("ParentId")) {
                                parentid = o.toString();
                            } else {
                                fields.put(field, t);
                            }
                        } else {
                            fields.put(field, t);
                        }
                    } else {
                        if (indexable(met.getReturnType().getSimpleName())) {
                            fields.put(field, met.getReturnType().getSimpleName());
                        } else {
                            //System.out.println(obj.getClass()+" field 3:"+field+" "+met.getReturnType().getSimpleName()+" "+indexable(met.getReturnType().getSimpleName()));
                        }
                    }
                } catch (Exception f) {
                    //throw f;
                    f.printStackTrace();
                    // attempt a get.
                }
            }
        }

        return fields;
    }

    /**
    * use this method to instantiate an object given an XML document and the reference class.
    *
    * @param  xml string contents containing the elements and values for the object.
    * @param  c the reference class that wil be used for instantiation.
    * @return the instantiated and value-populated object.
    * @see Hashtable
    * @see Element
    */
    public Object getObject(String xml, Class c) throws Exception {
        Object obj = c.newInstance();

        XMLConfiguration x = new XMLConfiguration();
        x.setDelimiterParsingDisabled(true);
        x.load(new ByteArrayInputStream(xml.getBytes()));
        Iterator it = x.getKeys();

        //Method[] m = c.getMethods();
        Vector ve = retrieveMethods(obj.getClass(), null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        String method = null;
        String type = null;

        boolean hasmethod = false;
        while (it.hasNext()) {
            String s = (String) it.next();
            // make sure they have the same type?
            if (s.contains("[@")) {
                type = x.getString(s);
                if (method != null) {
                    hasmethod = true;
                }
            } else {
                method = s;
            }

            if (hasmethod && type != null && method != null) {

                // check if class has the method.
                for (int i = 0; i < m.length; i++) {
                    if (m[i].getName().toLowerCase().equals("set" + method)) {
                        Object[] o = new Object[1];
                        Class ct = null;

                        if (type.endsWith("String")) {
                            ct = String.class;
                            o[0] = x.getString(method);
                        } else if (type.endsWith("XMLGregorianCalendar") || type.equalsIgnoreCase("timestamp")) {
                            // dirty 'temporary' workaround
                            // 2009-01-01T10:00:00.000+08:00
                            Date d = null;
                            try {
                                d = new Date(Long.parseLong(x.getString(method)));
                            } catch (Exception a) {
                                try {
                                    d = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S"))
                                            .parse(x.getString(method));
                                } catch (Exception e) {
                                    try {
                                        d = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
                                                .parse(x.getString(method));
                                    } catch (Exception f) {
                                        try // must be a date only
                                        {
                                            d = (new SimpleDateFormat("yyyy-MM-dd")).parse(x.getString(method));
                                        } catch (Exception g) // ok must be a time?
                                        {
                                            d = (new SimpleDateFormat("HH:mm:ss")).parse(x.getString(method));
                                        }
                                    }
                                }
                            }
                            GregorianCalendar gc = new GregorianCalendar();
                            gc.setTime(d);

                            XMLGregorianCalendar cal = ((new com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl())
                                    .newXMLGregorianCalendar(gc));
                            ct = XMLGregorianCalendar.class;
                            o[0] = cal;
                        } else if (type.endsWith("Date")) {
                            ct = Date.class;
                            // assume use default java date format
                            //o[0] = (new SimpleDateFormat("EEE MMM d HH:mm:ss Z yyyy")).parse(x.getString(method));
                            try {
                                o[0] = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(x.getString(method));
                            } catch (Exception e) {
                                //if not must be in long version
                                //o[0] = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date(Long.parseLong(x.getString(method))));
                                o[0] = new Date(Long.parseLong(x.getString(method)));
                            }
                        } else if (type.endsWith("BigInteger")) {
                            ct = BigInteger.class;
                            o[0] = new BigInteger(x.getString(method));
                        } else if (type.endsWith("BigDecimal")) {
                            ct = BigDecimal.class;
                            o[0] = new BigDecimal(x.getString(method));
                        } else if (type.endsWith(".Integer") || type.equals("Integer")
                                || type.equalsIgnoreCase("int unsigned") || type.equalsIgnoreCase("tinyint")) {
                            ct = Integer.class;
                            o[0] = x.getInt(method);
                        } else if (type.endsWith("Long")) {
                            ct = Long.class;
                            o[0] = x.getLong(method);
                        } else if (type.endsWith("Double")) {
                            ct = Double.class;
                            o[0] = x.getDouble(method);
                        } else if (type.endsWith("Float")) {
                            ct = Float.class;
                            o[0] = x.getFloat(method);
                        } else if (type.endsWith("Short")) {
                            ct = Short.class;
                            o[0] = x.getShort(method);
                        } else if (type.endsWith("boolean")) {
                            ct = boolean.class;
                            o[0] = x.getBoolean(method);
                        } else if (type.endsWith("Boolean")) {
                            ct = Boolean.class;
                            o[0] = x.getBoolean(method);
                        } else if (type.endsWith("byte[]")) {
                            ct = byte[].class;
                            o[0] = x.getString(method).getBytes();
                        } else if (type.endsWith("Serializable")) {
                            ct = Serializable.class;
                            o[0] = x.getString(method).getBytes();
                        } else {
                            throw new Exception("Unknown type:" + type + " for element:" + method);
                        }

                        Class[] c2 = new Class[1];
                        c2[0] = ct;
                        //Method met = c.getMethod("set"+method,c2);
                        Method met = c.getMethod(m[i].getName(), c2);
                        met.invoke(obj, o);

                        break;
                    }
                }
                type = null;
                method = null;
                hasmethod = false;
            }
        }
        return obj;
    }

    /**
    * use this method to instantiate a JAXB object encapsulated in a FlexContainer, given an XML document and the reference class.
    *
    * @param  xml string contents containing the elements and values for the object.
    * @param  c the reference class that wil be used for instantiation.
    * @return the instantiated and value-populated object.
    * @see Hashtable
    * @see Element
    */
    public Object getJAXBObject(String xml, Class c) throws Exception {
        Object obj = c.newInstance();
        Object fc = new FlexContainer(obj);

        XMLConfiguration x = new XMLConfiguration();
        x.setDelimiterParsingDisabled(true);
        x.load(new ByteArrayInputStream(xml.getBytes()));
        Iterator it = x.getKeys();

        //Method[] m = c.getMethods();
        Vector ve = retrieveMethods(obj.getClass(), null);
        Method[] m = new Method[ve.size()];
        ve.toArray(m);

        String method = null;
        String type = null;

        boolean hasmethod = false;
        while (it.hasNext()) {
            String s = (String) it.next();
            // make sure they have the same type?
            if (s.contains("[@")) {
                type = x.getString(s);
                if (method != null) {
                    hasmethod = true;
                }
            } else {
                method = s;
            }

            if (hasmethod && type != null && method != null) {
                // check if class has the method.
                for (int i = 0; i < m.length; i++) {
                    if (m[i].getName().toLowerCase().equals("set" + method)) {

                        Object[] o = new Object[1];
                        Class ct = null;

                        if (type.endsWith("String")) {
                            ct = String.class;
                            o[0] = x.getString(method);
                        } else if (type.endsWith("Date")) {
                            ct = Date.class;
                            // assume use default java date format
                            //o[0] = (new SimpleDateFormat("EEE MMM d HH:mm:ss Z yyyy")).parse(x.getString(method));
                            o[0] = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(x.getString(method));
                        } else if (type.endsWith("BigInteger")) {
                            ct = BigInteger.class;
                            o[0] = new BigInteger(x.getString(method));
                        } else if (type.endsWith("BigDecimal")) {
                            ct = BigDecimal.class;
                            o[0] = new BigDecimal(x.getString(method));
                        } else if (type.endsWith(".Integer")) {
                            ct = Integer.class;
                            o[0] = x.getInt(method);
                        } else if (type.endsWith("Long")) {
                            ct = Long.class;
                            o[0] = x.getLong(method);
                        } else if (type.endsWith("Double")) {
                            ct = Double.class;
                            o[0] = x.getDouble(method);
                        } else if (type.endsWith("Float")) {
                            ct = Float.class;
                            o[0] = x.getFloat(method);
                        } else if (type.endsWith("Short")) {
                            ct = Short.class;
                            o[0] = x.getShort(method);
                        } else if (type.endsWith("boolean")) {
                            ct = boolean.class;
                            o[0] = x.getBoolean(method);
                        } else if (type.endsWith("Boolean")) {
                            ct = Boolean.class;
                            o[0] = x.getBoolean(method);
                        } else if (type.endsWith("byte[]")) {
                            ct = byte[].class;
                            o[0] = Base64.decodeBase64(x.getString(method).getBytes());
                        } else if (type.endsWith("Serializable")) {
                            ct = Serializable.class;
                            o[0] = getObject(Base64.decodeBase64(x.getString(method).getBytes()));
                        } else {
                            throw new Exception("Unknown type:" + type + " for element:" + method);
                        }

                        Class[] c2 = new Class[1];
                        c2[0] = ct;
                        //Method met = c.getMethod("set"+method,c2);
                        Method met = c.getMethod(m[i].getName(), c2);
                        met.invoke(obj, o);
                        break;
                    }
                }
                type = null;
                method = null;
                hasmethod = false;
            }
        }
        return obj;
    }

    /**
    * use this method to obtain a mimemessage with the file wrapped in it.
    *
    * @param  filename filename of the file.
    * @param  data the file in bytes.
    * @return a byte array of the mimemessage.
    */
    static public byte[] wrapInMimeMessage(String filename, byte[] data) throws Exception {
        MimeMessage mimemessage = new MimeMessage(javax.mail.Session.getDefaultInstance(new Properties(), null));
        BodyPart messageBodyPart = new MimeBodyPart();
        Multipart multipart = new MimeMultipart();
        DataSource source = new ByteArrayDataSource(data, "application/octet-stream");
        messageBodyPart.setDataHandler(new DataHandler(source));
        messageBodyPart.setFileName(filename);
        multipart.addBodyPart(messageBodyPart);
        mimemessage.setContent(multipart);
        mimemessage.saveChanges();

        // finally pipe to an array so we can conver to string
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        mimemessage.writeTo(bos);
        return bos.toString().getBytes();
    }

    /**
    * method to obtain a FileContainer containing the file wrapped in a mimemessage.
    *
    * @param  data the mimemessage in a byte array.
    * @return a FileContainer containing the file.
    */
    static public FileContainer extractFileFromMimeMessage(byte[] data) throws Exception {
        FileContainer fc = null;
        MimeMessage message = new MimeMessage(null, new ByteArrayInputStream(data));
        Object content = message.getContent();

        if (content instanceof Multipart) {
            Multipart multipart = (Multipart) content;
            for (int i = 0, n = multipart.getCount(); i < n; i++) {
                Part part = multipart.getBodyPart(i);
                String disposition = part.getDisposition();

                if ((disposition != null)
                        && (disposition.equals(Part.ATTACHMENT) || (disposition.equals(Part.INLINE)))) {
                    if (part.getFileName() != null) {
                        fc = new FileContainer(part.getFileName(), part.getFileName(),
                                getBytesFromInputStream(part.getInputStream()));
                        break;
                    }
                }
            }
        }
        return fc;
    }

    static public void createTextBanner(String text, int fontsize, int width, int height, int x, int y,
            String outputfile) throws Exception {
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        img.createGraphics();
        Graphics2D g = (Graphics2D) img.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, img.getWidth(), img.getHeight());
        Font font = new Font("Arial", Font.BOLD, fontsize);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
        g.setFont(font);
        g.setColor(Color.BLUE.darker());
        g.drawString(text, x, y);
        ImageIO.write(img, "png", new File(outputfile));
    }

    static public ResultPacket createCaptchaImage(String sessionid, String text, String type) throws Exception {
        ResultPacket res = new ResultPacket();

        ByteArrayOutputStream outStream = new ByteArrayOutputStream();

        BufferedImage img = createCaptcha(text, Color.gray, Color.gray.darker(), 24, text.length() * 16, 30, 5, 25);
        ImageIO.write(img, "png", outStream);

        res.setPayload(outStream.toByteArray());
        res.setDescription(sessionid + (new Date()).getTime() + ".png"); // this will force the browser to refresh the image

        return res;

    }

    static public BufferedImage createCaptcha(String text, Color background, Color fontcolor, int fontsize,
            int width, int height, int x, int y) throws Exception {
        BufferedImage img = new BufferedImage(width + 10, height, BufferedImage.TYPE_INT_RGB);
        img.createGraphics();
        Graphics2D g = (Graphics2D) img.getGraphics();
        g.setColor(background);
        g.fillRect(0, 0, img.getWidth(), img.getHeight());
        Font font = new Font("Monospaced", Font.BOLD + Font.ITALIC, fontsize);

        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
        g.setFont(font);
        g.setColor(fontcolor);

        char[] c = text.toCharArray();

        java.util.Random random = new java.util.Random();

        for (int i = 0; i < c.length; i++) {
            int j = random.nextInt(9);
            if (j > 5) {
                j = j - 5;
            } else {
                j = -1 * (j - 2);
            }

            char[] c1 = new char[1];
            c1[0] = c[i];
            g.drawChars(c1, 0, 1, x + (i * 16), y + j);
        }

        for (int i = -10; i < 20; i++) {
            int j = random.nextInt(8);
            g.drawOval((i + j) - 20, ((i * 8) - (j > 3 ? 4 : -4)), width + 20, height);
        }
        //ImageIO.write(img,"png",new File(outputfile));
        return img;

    }

    static public boolean indexable(String type) {
        return _indexabletypes.indexOf(type) > -1;
    }

    static public String replaceString(String sourcefile, String lookfor, String replacewith) throws Exception {

        int i;

        sourcefile = sourcefile == null ? "" : sourcefile;

        if (replacewith.indexOf(lookfor) < 0) {
            while ((i = sourcefile.lastIndexOf(lookfor)) >= 0) {
                sourcefile = sourcefile.substring(0, i).concat(replacewith)
                        .concat(sourcefile.substring(i + lookfor.length(), sourcefile.length()));
            }
        } else {
            throw new Exception("String Replacement Error: Trying to replace " + lookfor + " with " + replacewith
                    + " will result in loop. Replacement is ignored.");
        }

        return sourcefile;

    }

    static public String replaceFirstString(String sourcefile, String lookfor, String replacewith)
            throws Exception {

        int i;

        if (replacewith.indexOf(lookfor) < 0) {
            if ((i = sourcefile.lastIndexOf(lookfor)) >= 0) {
                sourcefile = sourcefile.substring(0, i).concat(replacewith)
                        .concat(sourcefile.substring(i + lookfor.length(), sourcefile.length()));
            }
        } else {
            throw new Exception("String Replacement Error: Trying to replace " + lookfor + " with " + replacewith
                    + " will result in loop. Replacement is ignored.");
        }

        return sourcefile;

    }

    static public String generateKey(int codelength) {
        return (new Date()).getTime() + generateRandomCode(codelength - 13);
    }

    static public String generateRandomCode(int codelength) {
        return generateRandomCode(codelength, true);
    }

    static public String generateRandomCode(int codelength, boolean lowcaseonly) {
        java.util.Random random = new java.util.Random();
        int i, j, k;
        StringBuffer result = new StringBuffer();
        String[] a = null;

        if (lowcaseonly) {
            // required to declare in another var as I get a wrong IDE error if I use variable "a" declared above.
            String[] b = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
                    "s", "t", "u", "v", "w", "x", "y", "z" };
            a = b;

        } else {
            String[] b = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
                    "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
                    "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
            a = b;
        }

        j = a.length - 1;

        for (k = 1; k <= codelength; k++) {
            // if i >= 5 then we choose from letters
            if (random.nextInt(9) > (lowcaseonly ? 5 : 3)) {
                i = random.nextInt(j);
                result.append(a[i]);
            } else // we choose from 0 to 9
            {
                //result=result+random.nextInt(9);
                result.append(random.nextInt(9));
            }
        }
        return result.toString();

    }

    static public byte[] getFileInBytes(String f) throws Exception {
        boolean haserror = false;
        Throwable t = null;
        byte[] data = null;
        RandomAccessFile rf = null;
        try {
            rf = new RandomAccessFile(f, "r");
            int size = (int) rf.length();
            data = new byte[size];
            rf.readFully(data);
        } catch (Exception e) {
            t = e;
            haserror = true;
        } finally {
            if (rf != null) {
                rf.close();
            }

            if (haserror) {
                throw new Exception(t);
            }

        }
        return data;
    }

    static public byte[] getBytes(Object obj) throws Exception {
        byte[] b = null;
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();
            b = bos.toByteArray();
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                oos.close();
                bos.close();
            } catch (Exception f) {
            }
        }
        return b;
    }

    static public Object getObject(byte[] b) throws Exception {
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        Object obj = null;
        try {
            bis = new ByteArrayInputStream(b);
            ois = new ObjectInputStream(bis);
            obj = ois.readObject();
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                ois.close();
                bis.close();
            } catch (Exception f) {
            }
        }
        return obj;
    }

    static public byte[] getBytesFromInputStream(InputStream is) throws Exception {
        int k;
        byte buff[] = new byte[1024];
        ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
        while ((k = is.read(buff)) != -1) {
            os.write(buff, 0, k);
        }

        return os.toByteArray();
    }

    // from http://www.kodejava.org/examples/266.html
    public String convertStreamToString(InputStream is) {
        /*
         * To convert the InputStream to String we use the BufferedReader.readLine()
         * method. We iterate until the BufferedReader return null which means
         * there's no more data to read. Each line will appended to a StringBuilder
         * and returned as String.
         */
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }

    // from http://www.javadb.com/read-from-file-with-bufferedinputstream
    static public String BufferedInputStreamToString(InputStream bufferedInput) {

        StringBuffer result = new StringBuffer();
        byte[] buffer = new byte[1024];

        try {

            int bytesRead = 0;

            //Keep reading from the file while there is any content
            //when the end of the stream has been reached, -1 is returned
            while ((bytesRead = bufferedInput.read(buffer)) != -1) {

                //Process the chunk of bytes read
                //in this case we just construct a String and print it out
                String chunk = new String(buffer, 0, bytesRead);
                result.append(chunk);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            //Close the BufferedInputStream
            try {
                if (bufferedInput != null)
                    bufferedInput.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result.substring(0);
    }

    public String transform(ErrorListener listener, Object xsl, Object xml) {
        String result = "Unable to transform";
        // get the XSL file
        try {
            TransformerFactory tFactory = TransformerFactory.newInstance();
            if (listener != null)
                tFactory.setErrorListener(listener);

            StreamSource stylesource = null;
            if (xsl instanceof File) {
                stylesource = new StreamSource(new FileInputStream((File) xsl));
            } else {
                stylesource = new StreamSource(new ByteArrayInputStream(((String) xsl).getBytes()));
            }

            Source source = null;
            if (xml instanceof File) {
                source = new StreamSource(new FileInputStream((File) xml));
            } else {
                source = new StreamSource(new ByteArrayInputStream(((String) xml).getBytes()));
            }

            if (stylesource != null) {
                Transformer transformer = tFactory.newTransformer(stylesource);
                // create a receiver object of the transformation.
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                StreamResult res = new StreamResult(out);
                // transform!
                transformer.transform(source, res);
                // done!
                //result = out.toString().trim();
                result = replaceString(replaceString(out.toString(), " &lt;", "<"), "/&gt;", "/>");

            }
        } catch (Exception e) {
            // return error.
            result = e.getMessage();
        }

        return result;
    }

    static public void saveStringToFile(String filepath, String content) throws Exception {
        ByteArrayInputStream is = new ByteArrayInputStream(content.getBytes());
        java.io.FileOutputStream fos = new java.io.FileOutputStream(new File(filepath));
        while (is.available() > 0) {
            fos.write(is.read());
        }
        fos.close();
        is.close();
    }

    static public void saveBytesToFile(String filepath, byte[] data) throws Exception {
        ByteArrayInputStream is = new ByteArrayInputStream(data);
        java.io.FileOutputStream fos = new java.io.FileOutputStream(new File(filepath));
        while (is.available() > 0) {
            fos.write(is.read());
        }
        fos.close();
        is.close();
    }

    static public String pad(int l) {
        String p = "";
        for (int i = 0; i < l; i++) {
            p = p + " ";
        }
        return p;
    }

    public static FlexElement getElementFromRoot(FlexElement flexelement, String object) {
        FlexElement element = null;

        try {
            // first check if the object can be found as a child in this element.
            element = flexelement.getElementByName(object);
        } catch (Exception f) {
        }

        try {
            // if the parent does not have it, check its children
            if (element == null && flexelement.retrieveElements() != null) {
                Enumeration en = flexelement.retrieveElements();
                while (en.hasMoreElements() && element == null) {
                    FlexElement el = (FlexElement) en.nextElement();
                    if (!el.getName().equals(flexelement.getName())) // we dont want to refer to ourselves.
                    {
                        element = getElementFromRoot(el, object);
                    }
                }
            }
        } catch (Exception f) {
        }

        return element;
    }

    static public Hashtable<Method, Class> retrieveMethodsWithTypeClasses(Class c, Hashtable met) {
        Hashtable<Method, Class> methods = (met == null ? new Hashtable<Method, Class>() : met);

        try {
            // if this generates a fault then it must be abstract and we ignore it.
            c.newInstance();

            Method[] m = c.getMethods();
            int x = 0;
            for (int i = 0; i < m.length; i++) {
                if (m[i].getReturnType() != null && !m[i].getReturnType().getSimpleName().equals("Class")) {
                    methods.put(m[i], c);
                }
            }

            // check for superclass
            Class sc = c.getSuperclass();
            if (!sc.getSimpleName().equals("Object")) {
                met = retrieveMethodsWithTypeClasses(sc, met);
            }

        } catch (Exception e) {
            //e.printStackTrace();
        }
        return methods;
    }

    static public Object getObjectMethodGetResult(Object obj, String plainmethod) throws Exception {
        Object o = null;
        // if this generates a fault then it must be abstract and we ignore it.
        Class c = obj.getClass();

        Method[] m = c.getMethods();
        int x = 0;
        for (int i = 0; i < m.length; i++) {
            if (m[i].getReturnType() != null && m[i].getName().equalsIgnoreCase("get" + proper(plainmethod))) {

                o = m[i].invoke(obj, (Object[]) null);
                break;
                //methods.put(m[i],c);
            }
        }

        return o;
    }

    static public void setObjectMethod(Object obj, String plainmethod, Object val) throws Exception {
        Object o = null;
        // if this generates a fault then it must be abstract and we ignore it.
        Class c = obj.getClass();

        Method[] m = c.getMethods();
        int x = 0;
        for (int i = 0; i < m.length; i++) {
            if (m[i].getName().equalsIgnoreCase("set" + proper(plainmethod))) {
                Object[] o2 = new Object[1];
                o2[0] = val;
                o = m[i].invoke(obj, o2);
                break;
                //methods.put(m[i],c);
            }
        }
    }

    static public Vector<Method> retrieveMethods(Class c, Vector<Method> met) {
        Vector<Method> methods = (met == null ? new Vector<Method>() : met);

        try {
            // if this generates a fault then it must be abstract and we ignore it.
            c.newInstance();

            Method[] m = c.getMethods();
            int x = 0;
            for (int i = 0; i < m.length; i++) {
                if (m[i].getReturnType() != null && !m[i].getReturnType().getSimpleName().equals("Class")) {
                    methods.add(m[i]);
                }
            }

            // check for superclass
            Class sc = c.getSuperclass();
            if (!sc.getSimpleName().equals("Object")) {
                met = (Vector<Method>) retrieveMethods(sc, met);
            }

        } catch (Exception e) {
            //e.printStackTrace();
        }
        return methods;
    }

    // database mapping utilities
    static public String getRDBMSRecordAsXML(String tablename, RecordSet rec, String idcolumn,
            String parentidcolumn, boolean includeidcolumns) throws Exception {
        return getRDBMSRecordAsXML(tablename, rec, idcolumn, parentidcolumn, includeidcolumns, false);
    }

    static public String getRDBMSRecordAsXML(String tablename, RecordSet rec, String idcolumn,
            String parentidcolumn, boolean includeidcolumns, boolean listall) throws Exception {
        StringBuffer res = new StringBuffer();
        int size = rec.size();

        if (size > 0) {
            // first we get the table struc
            Enumeration en = rec.getColumnNames();

            ConcurrentHashMap<String, String> columns = new ConcurrentHashMap<String, String>();

            while (en.hasMoreElements()) {
                String cname = (String) en.nextElement();
                String type = rec.getColumnType(cname);
                columns.put(cname.toLowerCase(), type);
            }

            boolean done = false;

            int i = 0;
            while (i < rec.size() && !done) {

                res.append("<" + tablename + ">");

                en = columns.keys();

                while (en.hasMoreElements()) {

                    String cname = ((String) en.nextElement()).toLowerCase();
                    String type = columns.get(cname);

                    boolean readrec = includeidcolumns;

                    if (!readrec) {
                        readrec = (!cname.equalsIgnoreCase(idcolumn) && !cname.equalsIgnoreCase(parentidcolumn));
                    }

                    if (readrec) {
                        if (type.toUpperCase().indexOf("BLOB") > -1 || type.toUpperCase().indexOf("BINARY") > -1) {
                            Object o = rec.getContent(cname);

                            if (o instanceof com.mysql.jdbc.Blob) {
                                //byte[] b = BufferedInputStreamToString(((com.mysql.jdbc.Blob)o).getBinaryStream()).getBytes();
                                Blob blob = ((Blob) o);
                                byte[] b = blob.getBytes(1, (int) blob.length());

                                res.append("<" + cname + " type=\"byte[]\"><![CDATA[" + new String(b) + "]]></"
                                        + cname + ">");
                            } else {
                                res.append("<" + cname + " type=\"byte[]\"><![CDATA[" + o + "]]></" + cname + ">");
                            }

                        } else if (type.indexOf("CHAR") > -1 || type.indexOf("TEXT") > -1) {
                            res.append("<" + cname + " type=\"String\"><![CDATA["
                                    + stripNonValidChars(rec.getString(cname)) + "]]></" + cname + ">");
                        } else if (type.equalsIgnoreCase("DATE") || type.equalsIgnoreCase("DATETIME")
                                || type.equalsIgnoreCase("TIMESTAMP")
                                || (type != null && type.toUpperCase().equals("YEAR"))) {
                            res.append("<" + cname + " type=\"XMLGregorianCalendar\"><![CDATA["
                                    + rec.getString(cname) + "]]></" + cname + ">");
                        } else if (type.equalsIgnoreCase("LONG") || type.equalsIgnoreCase("TINY")
                                || type.equalsIgnoreCase("BIT") || type.equalsIgnoreCase("BIGINT")
                                || type.equalsIgnoreCase("SMALLINT") || type.equalsIgnoreCase("TINYINT")
                                || type.equalsIgnoreCase("MEDIUMINT") || type.equalsIgnoreCase("INT")) {
                            res.append("<" + cname + " type=\"BigInteger\"><![CDATA[" + rec.getInt(cname) + "]]></"
                                    + cname + ">");
                        } else if (type.equalsIgnoreCase("DOUBLE") || type.equalsIgnoreCase("NUMERIC")
                                || type.equalsIgnoreCase("DECIMAL")) {
                            res.append("<" + cname + " type=\"Double\"><![CDATA[" + rec.getDouble(cname) + "]]></"
                                    + cname + ">");
                        } else if (type.equalsIgnoreCase("FLOAT")) {
                            res.append("<" + cname + " type=\"Float\"><![CDATA[" + rec.getFloat(cname) + "]]></"
                                    + cname + ">");
                        }
                        /*else if (type.equalsIgnoreCase("LONG"))
                        {
                        res.append("<"+proper(cname)+" type=\"Long\"><![CDATA["+rec.getDouble(cname)+"]]></"+proper(cname)+">");
                        }*/
                        else {
                            //res.append("<"+proper(cname)+" type=\""+cname+"\"><![CDATA["+rec.getString(cname)+"]]></"+proper(cname)+">");
                            throw new Exception(cname + " type " + type + " is not recognized.");
                        }
                    }
                }

                res.append("</" + tablename + ">\n");

                if (!listall) {
                    done = true;
                } else {
                    i++;
                    rec.next();
                }
            }
        }

        return new String(res.substring(0).getBytes("UTF8"));
    }

    static public String getRDBMSRecordAsXML(String tablename, RecordSet rec, String idcolumn,
            String parentidcolumn, boolean includeidcolumns, FlexElement idelement) throws Exception {
        StringBuffer res = new StringBuffer();
        int size = rec.size();

        if (size > 0) {
            // first we get the table struc
            Enumeration en = rec.getColumnNames();

            ConcurrentHashMap<String, String> columns = new ConcurrentHashMap<String, String>();

            while (en.hasMoreElements()) {
                String cname = (String) en.nextElement();
                String type = rec.getColumnType(cname);
                columns.put(cname.toLowerCase(), type);
            }

            res.append("<" + tablename + ">");

            en = columns.keys();

            String cname = "";
            FlexElement aliascolumn = null;

            while (en.hasMoreElements()) {
                aliascolumn = null;
                cname = "";

                cname = (String) en.nextElement();
                String objectField = "";
                aliascolumn = (FlexElement) idelement.getElementByName(cname.trim(), false);

                if (aliascolumn == null) {
                    objectField = cname;
                } else {
                    if (aliascolumn.getAttribute("alias") == null) {
                        objectField = cname;
                    } else {
                        objectField = aliascolumn.getAttribute("alias").getValue();
                    }
                }

                String type = columns.get(cname);

                boolean readrec = includeidcolumns;

                if (!readrec) {
                    readrec = (!cname.equalsIgnoreCase(idcolumn) && !cname.equalsIgnoreCase(parentidcolumn));
                }

                if (readrec) {
                    if (type.toUpperCase().indexOf("BLOB") > -1 || type.toUpperCase().indexOf("BINARY") > -1) {
                        Object o = rec.getContent(cname);

                        if (o != null) {
                            //System.out.print(cname+")type:"+type+" "+o.getClass());

                            Blob blob = ((Blob) o);

                            byte[] b = blob.getBytes(1, (int) blob.length());
                            res.append("<" + objectField + " type=\"byte[]\"><![CDATA[" + new String(b) + "]]></"
                                    + objectField + ">");
                        } else {
                            res.append("<" + objectField + " type=\"byte[]\"><![CDATA[]]></" + objectField + ">");
                        }
                    } else if (type.indexOf("CHAR") > -1 || type.indexOf("TEXT") > -1
                            || type.toUpperCase().equals("YEAR")) {
                        res.append("<" + objectField + " type=\"String\"><![CDATA[" + rec.getString(cname) + "]]></"
                                + objectField + ">");
                    } else if (type.equalsIgnoreCase("DATETIME") || type.equalsIgnoreCase("TIMESTAMP")
                            || type.toUpperCase().equals("DATE") || type.toUpperCase().equals("TIME")) {
                        res.append("<" + objectField + " type=\"XMLGregorianCalendar\"><![CDATA["
                                + rec.getString(cname) + "]]></" + objectField + ">");
                    } else if (type.equalsIgnoreCase("LONG") || type.equalsIgnoreCase("TINY")
                            || type.equalsIgnoreCase("BIT") || type.equalsIgnoreCase("BIGINT")
                            || type.equalsIgnoreCase("SMALLINT") || type.equalsIgnoreCase("TINYINT")
                            || type.equalsIgnoreCase("MEDIUMINT") || type.equalsIgnoreCase("INT")) {
                        res.append("<" + objectField + " type=\"BigInteger\"><![CDATA[" + rec.getInt(cname)
                                + "]]></" + objectField + ">");
                    } else if (type.equalsIgnoreCase("DOUBLE") || type.equalsIgnoreCase("NUMERIC")
                            || type.equalsIgnoreCase("DECIMAL")) {
                        res.append("<" + objectField + " type=\"Double\"><![CDATA[" + rec.getDouble(cname) + "]]></"
                                + objectField + ">");
                    } else if (type.equalsIgnoreCase("FLOAT")) {
                        res.append("<" + objectField + " type=\"Float\"><![CDATA[" + rec.getFloat(cname) + "]]></"
                                + objectField + ">");
                    }
                    /*else if (type.equalsIgnoreCase("LONG"))
                    {
                    res.append("<"+proper(cname)+" type=\"Long\"><![CDATA["+rec.getDouble(cname)+"]]></"+proper(cname)+">");
                    }*/
                    else {
                        //res.append("<"+proper(objectField)+" type=\""+cname+"\"><![CDATA["+rec.getString(cname)+"]]></"+proper(objectField)+">");
                        throw new Exception(objectField + " type " + type + " is not recognized.");
                    }
                }
            }
            res.append("</" + tablename + ">");
        }

        //System.out.println(">>>1:"+res.toString());
        return new String(res.substring(0).getBytes("UTF8"));
    }

    static public String getRDBMSTableStructureAsXML(String tablename, ResultSet result) {

        StringBuffer res = new StringBuffer();

        try {

            RecordSet rec = new RecordSet(result);
            int size = rec.size();

            if (size > 0) {
                Enumeration en = rec.getColumnNames();

                res.append("<" + tablename + ">");

                while (en.hasMoreElements()) {
                    String cname = (String) en.nextElement();
                    String type = rec.getColumnType(cname);

                    if (type.toUpperCase().indexOf("BLOB") > -1 && type.toUpperCase().indexOf("BINARY") > -1) {
                        res.append("<" + cname + " type=\"byte[]\"/>");
                    } else {
                        res.append("<" + cname + " type=\"" + type + "\"/>");
                    }
                }

                res.append("</" + tablename + ">");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return res.substring(0);
    }

    static public FlexElement getRDBMSTableStructureAsFlexElement(String tablename, ResultSet result) {
        FlexElement element = new FlexElement(tablename);
        try {
            RecordSet rec = new RecordSet(result);
            int size = rec.size();

            if (size > 0) {
                Enumeration en = rec.getColumnNames();

                while (en.hasMoreElements()) {
                    String cname = (String) en.nextElement();
                    String type = rec.getColumnType(cname);
                    boolean isautoincrement = rec.isAutoIncrement(cname);

                    if (type.toUpperCase().indexOf("BLOB") > -1 || type.toUpperCase().indexOf("BINARY") > -1) {
                        element.addElement((new FlexElement(cname)).setType("base64Binary")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else if (type.indexOf("CHAR") > -1 || type.indexOf("TEXT") > -1) {
                        element.addElement((new FlexElement(cname)).setType("string")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else if (type.equalsIgnoreCase("DATETIME") || type.equalsIgnoreCase("TIMESTAMP")) {
                        element.addElement((new FlexElement(cname)).setType("dateTime")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else if (type.toUpperCase().startsWith("YEAR")) {
                        element.addElement((new FlexElement(cname)).setType("date")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else if (type.equalsIgnoreCase("BIT") || type.equalsIgnoreCase("TINY")
                            || type.equalsIgnoreCase("BIGINT") || type.equalsIgnoreCase("SMALLINT")
                            || type.equalsIgnoreCase("TINYINT") || type.equalsIgnoreCase("MEDIUMINT")
                            || type.equalsIgnoreCase("INT") || type.equalsIgnoreCase("INT UNSIGNED")
                            || type.equalsIgnoreCase("INT SIGNED")) {
                        element.addElement((new FlexElement(cname)).setType("integer")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else if (type.equalsIgnoreCase("DOUBLE") || type.equalsIgnoreCase("NUMERIC")
                            || type.equalsIgnoreCase("DECIMAL")) {
                        element.addElement((new FlexElement(cname)).setType("double")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else if (type.equalsIgnoreCase("FLOAT")) {
                        element.addElement((new FlexElement(cname)).setType("float")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else if (type.equalsIgnoreCase("LONG")) {
                        element.addElement((new FlexElement(cname)).setType("long")
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    } else {
                        element.addElement((new FlexElement(cname)).setType(type.toLowerCase())
                                .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return element;
    }

    static public FlexElement getRDBMSTableDescriptionAsFlexElement(String tablename, ResultSet result) {
        FlexElement element = new FlexElement(tablename);
        try {
            while (result != null && result.next()) {
                String cname = result.getString("Field");
                String type = result.getString("Type").toUpperCase();

                //System.out.print(type+" ("+cname+"), ");

                boolean isautoincrement = result.getString("Extra").indexOf("auto_increment") > -1;

                if (type.toUpperCase().indexOf("BLOB") > -1 || type.toUpperCase().indexOf("BINARY") > -1) {
                    element.addElement((new FlexElement(cname)).setType("base64Binary")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.indexOf("CHAR") > -1 || type.indexOf("TEXT") > -1
                        || type.toUpperCase().startsWith("YEAR")) {
                    element.addElement((new FlexElement(cname)).setType("string")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.indexOf("DATETIME") > -1 || type.indexOf("TIMESTAMP") > -1) {
                    element.addElement((new FlexElement(cname)).setType("dateTime")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.equals("DATE")) {
                    element.addElement((new FlexElement(cname)).setType("date")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.equalsIgnoreCase("TIME")) {
                    element.addElement((new FlexElement(cname)).setType("time")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.indexOf("BIT") > -1 || type.indexOf("TINY") > -1 || type.indexOf("BIGINT") > -1
                        || type.indexOf("SMALLINT") > -1 || type.indexOf("TINYINT") > -1
                        || type.indexOf("MEDIUMINT") > -1 || type.indexOf("INT") > -1
                        || type.indexOf("INT UNSIGNED") > -1 || type.indexOf("INT SIGNED") > -1) {
                    element.addElement((new FlexElement(cname)).setType("integer")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.indexOf("DOUBLE") > -1 || type.indexOf("NUMERIC") > -1
                        || type.indexOf("DECIMAL") > -1) {
                    element.addElement((new FlexElement(cname)).setType("double")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.indexOf("FLOAT") > -1) {
                    element.addElement((new FlexElement(cname)).setType("float")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else if (type.indexOf("LONG") > -1) {
                    element.addElement((new FlexElement(cname)).setType("long")
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                } else {
                    element.addElement((new FlexElement(cname)).setType(type.toLowerCase())
                            .addAttribute((new FlexAttribute("autoincrement")).setValue(isautoincrement + "")));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return element;
    }

    static public Hashtable getRDBMSRecordValues(ResultSet result) {
        Hashtable<String, Element> h = new Hashtable<String, Element>();
        try {
            RecordSet rec = new RecordSet(result);
            int size = rec.size();

            if (size > 0) {
                Enumeration en = rec.getColumnNames();

                while (en.hasMoreElements()) {
                    String cname = (String) en.nextElement();
                    String type = rec.getColumnType(cname);
                    h.put(cname, new Element(type, rec.getContent(cname)));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return h;
    }

    static public XMLGregorianCalendar getDate(String cal) throws Exception {
        //Date dfield_time = (cal.trim().length()==10?new SimpleDateFormat("yyyy-MM-dd"):new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(cal);
        return getCalendar(new SimpleDateFormat("yyyy-MM-dd").parse(cal));
    }

    static public XMLGregorianCalendar getDateTime(String cal) throws Exception {
        if (cal.trim().length() == 10) {
            cal = cal.trim() + " 00:00:00"; // we include the HH mm and ss
        }
        return getCalendar(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(cal));
    }

    static public XMLGregorianCalendar getTime(String cal) throws Exception {
        return getCalendar(new SimpleDateFormat("HH:mm:ss").parse(cal));
    }

    static public XMLGregorianCalendar getCalendar(Date d) {
        GregorianCalendar gcfield_time = new GregorianCalendar();
        gcfield_time.setTime(d);
        return (new com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl())
                .newXMLGregorianCalendar(gcfield_time);
    }

    static public String proper(String s) {
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    /**
    * given two date with the format 'yyyy-MM-dd' this will return the date ranges for months in a map. For example given a 'from' of '2009-12-10'
    * and a 'to' of '2010-03-05' this will return a map with contents [{'2009-12-10 00:00:00','2009-12-31 23:59:59'},{'2010-01-01 00:00:00','2010-01-31 23:59:59'},{'2010-02-01 00:00:00','2010-02-28 23:59:59'}]
    * which can be used for traversing data from tables (e.g. logs).
    *
    * @param from the starting date in the form (yyyy-MM-dd).
    * @param to the end date in the form (yyyy-MM-dd).
    * @return map of the object (sorted in natural order).
    */
    static public Map getDateRanges(String from, String to) throws Exception {

        SimpleDateFormat sdfd = new SimpleDateFormat("yyyyMM");
        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");

        Map<String, String> dateranges = new TreeMap<String, String>();

        // if the months are the same
        if (sdfd.parse(from).equals(sdfd.parse(to))) {
            dateranges.put(from + " 00:00:00", to + " 23:59:59");
        } else {
            long day = (1000 * 60 * 60 * 24);
            long days = (sdfDay.parse(to).getTime() / day) - (sdfDay.parse(from).getTime() / day);
            Calendar fromc = new GregorianCalendar();
            fromc.setTime(sdfDay.parse(from));

            String startday = from;
            int startmonth = Integer.parseInt(sdfd.format(sdfDay.parse(from)));
            String nowday = sdfDay.format(fromc.getTime());

            for (int i = 1; i <= days; i++) {
                fromc.add(Calendar.DATE, 1);
                Date now = fromc.getTime();
                // this measn it has moved to the next month
                if (startmonth < Integer.parseInt(sdfd.format(now))) {
                    // close it!
                    dateranges.put(startday + " 00:00:00", nowday + " 23:59:59");
                    startday = sdfDay.format(fromc.getTime());
                    startmonth = Integer.parseInt(sdfd.format(sdfDay.parse(startday)));
                }

                nowday = sdfDay.format(fromc.getTime());

            }

            dateranges.put(startday + " 00:00:00", nowday + " 23:59:59");

        }

        return dateranges;

        /*Iterator it = dateranges.keySet().iterator();
        while (it.hasNext())
        {
        String k = (String) it.next();
        System.out.println(k+" to "+dateranges.get(k));
        }*/

    }

    /**
    * given two date with the format 'yyyy-MM-dd' this will return the days within the dates in a Collection. For example given a 'from' of '2013-05-01'
    * and a 'to' of '2013-05-05' this will return a Collection with contents [{'2013-05-01','2013-05-02','2013-05-03','2013-05-04','2013-05-05'}]
    * which can be used for traversing data from tables (e.g. logs).
    *
    * @param from the starting date in the form (yyyy-MM-dd).
    * @param to the end date in the form (yyyy-MM-dd).
    * @return map of the object (sorted in natural order).
    */
    static public Collection getDaysBetween(String from, String to) throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Vector<String> daysbetween = new Vector<String>();

        // if the months are the same
        if (sdf.parse(from).equals(sdf.parse(to))) {
            daysbetween.add(from);
        } else {
            Calendar fromc = new GregorianCalendar();
            fromc.setTime(sdf.parse(from));

            Date t = sdf.parse(to);

            while (!fromc.getTime().after(t)) {
                daysbetween.add(sdf.format(fromc.getTime()));
                fromc.add(Calendar.DAY_OF_MONTH, 1);
            }

        }

        return daysbetween;

    }

    public static String stripNonValidChars(String str) {

        StringBuilder s = new StringBuilder();

        for (char c : str.toCharArray()) {

            if ((c == 0x9) || (c == 0xA) || (c == 0xD)

                    || ((c >= 0x20) && (c <= 0xD7FF))

                    || ((c >= 0xE000) && (c <= 0xFFFD))

                    || ((c >= 0x10000) && (c <= 0x10FFFF))) {

                s.append(c);

            }

        }

        return s.toString();

    }

    /*static public ResultPacket createImage(String sessionid, String text,String type) throws Exception
    {
    ResultPacket res = new ResultPacket();
    GradiatedBackgroundProducer gbp = new GradiatedBackgroundProducer();
    gbp.setFromColor(Color.DARK_GRAY);
        
    //FishEyeGimpyRenderer fegr = new FishEyeGimpyRenderer();
    GimpyRenderer ren = null;
        
    if (type!=null && type.equalsIgnoreCase("dropshadow"))
    {
        ren = new DropShadowGimpyRenderer();
        
    }
    else if (type!=null && type.equalsIgnoreCase("block"))
    {
        ren = new BlockGimpyRenderer();
        
    }
    else if (type!=null && type.equalsIgnoreCase("fisheye"))
    {
        ren = new FishEyeGimpyRenderer();
        
    }
    else
    {
        ren = new RippleGimpyRenderer();
    }
        
    Captcha captcha = new Captcha.Builder(200, 50).addBackground(gbp).gimp(ren).addNoise().build();
        
    WordRenderer wordRenderer = null;
        
    //ResultPacket res = new ResultPacket();
     ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    BufferedImage bi = captcha.getImage();
        
    wordRenderer = new DefaultWordRenderer();
    wordRenderer.render(text, bi);
        
    ImageIO.write(bi, "png", outStream);
        
    res.setPayload(outStream.toByteArray());
    res.setDescription(sessionid +(new Date()).getTime()+".png"); // this will force the browser to refresh the image
        
    return res;
        
    }*/

    static public boolean sendMail(String host, int port, String from, String to, String subject, String msg)
            throws Exception {
        SMTPTransport transport = null;
        boolean ok = false;
        try {
            InternetAddress[] rcptto = new InternetAddress[1];
            rcptto[0] = new InternetAddress(to);

            Properties props = System.getProperties();

            props.put("mail.smtp.host", host);
            props.put("mail.smtp.port", port + "");

            javax.mail.Session session = javax.mail.Session.getDefaultInstance(props, null);

            transport = (SMTPTransport) session.getTransport("smtp");

            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
            message.setSubject(subject);
            message.setSentDate(new Date());
            message.setContent(msg, "text/html");
            //Transport.send(message);

            transport.setLocalHost("REMOTE-CLIENT");
            transport.connect();
            transport.sendMessage(message, rcptto);

            ok = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                transport.close();
            } catch (Exception f) {
                f.printStackTrace();
            }
        }
        return ok;
    }

    static public String sendMailShowResult(String host, int port, String from, String to, String subject,
            String msg) throws Exception {
        String response = "OK";

        SMTPTransport transport = null;
        boolean ok = true;

        try {
            InternetAddress[] rcptto = new InternetAddress[1];
            rcptto[0] = new InternetAddress(to);

            Properties props = System.getProperties();

            props.put("mail.smtp.host", host);
            props.put("mail.smtp.port", port + "");
            props.put("mail.smtp.connectiontimeout", "60000"); // 300000 original
            props.put("mail.smtp.timeout", "60000");
            props.put("mail.smtp.quitwait", "false");

            javax.mail.Session session = javax.mail.Session.getInstance(props);

            transport = (SMTPTransport) session.getTransport("smtp");

            MimeMessage message = new MimeMessage(session);

            message.setFrom(new InternetAddress(from));

            message.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
            message.setSubject(subject);
            message.setSentDate(new Date());
            message.setContent(msg, "text/html");
            //Transport.send(message);
            transport.setLocalHost("REMOTE-CLIENT");
            transport.connect();
            transport.sendMessage(message, rcptto);

        } catch (Exception e) {
            e.printStackTrace();
            ok = false;
        } finally {

            try {
                if (!ok) {
                    response = "SENDING FAILED:" + transport.getLastServerResponse();
                } else {
                    response = "SENDING SUCCESS:" + transport.getLastServerResponse();
                }

                transport.close();

            } catch (Exception f) {

            }

        }
        return response;
    }

    static public String sendMailShowResult(String host, int port, String fromname, String from, String to,
            String subject, String msg) throws Exception {
        String response = "OK";

        SMTPTransport transport = null;
        boolean ok = true;

        try {
            InternetAddress[] rcptto = new InternetAddress[1];
            rcptto[0] = new InternetAddress(to);

            Properties props = System.getProperties();

            props.put("mail.smtp.host", host);
            props.put("mail.smtp.port", port + "");
            props.put("mail.smtp.connectiontimeout", "60000"); // 300000 original
            props.put("mail.smtp.timeout", "60000");
            props.put("mail.smtp.quitwait", "false");

            javax.mail.Session session = javax.mail.Session.getInstance(props);

            transport = (SMTPTransport) session.getTransport("smtp");

            MimeMessage message = new MimeMessage(session);
            if (fromname == null || fromname.isEmpty()) {
                message.setFrom(new InternetAddress(from));
            } else {
                message.setFrom(new InternetAddress(from, fromname));
            }
            message.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
            message.setSubject(subject);
            message.setSentDate(new Date());
            message.setContent(msg, "text/html");
            //Transport.send(message);
            transport.setLocalHost("REMOTE-CLIENT");
            transport.connect();
            transport.sendMessage(message, rcptto);

        } catch (Exception e) {
            e.printStackTrace();
            ok = false;
        } finally {

            try {
                if (!ok) {
                    response = "SENDING FAILED:" + transport.getLastServerResponse();
                } else {
                    response = "SENDING SUCCESS:" + transport.getLastServerResponse();
                }

                transport.close();

            } catch (Exception f) {

            }

        }
        return response;
    }

    static public String encryptdes(String passkey, String texttoencrypt) throws Exception {
        Security.addProvider(new com.sun.crypto.provider.SunJCE());
        byte key[] = passkey.trim().getBytes();
        DESKeySpec desKeySpec = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey desKey = keyFactory.generateSecret(desKeySpec);

        Cipher desCipher;

        // Create the cipher
        desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

        // Initialize the cipher for encryption
        desCipher.init(Cipher.ENCRYPT_MODE, desKey);

        // initialize base 64 encoding
        //org.apache.axis.encoding.Base64 base64 = new org.apache.axis.encoding.Base64();
        byte[] cleartext = texttoencrypt.getBytes();

        // Encrypt the cleartext
        byte[] ciphertext = desCipher.doFinal(cleartext);

        // encode to base64
        ciphertext = org.apache.axis.encoding.Base64.encode(ciphertext).getBytes();

        return new String(ciphertext);
    }

    static public String decryptdes(String passkey, String texttoencrypt) throws Exception {
        Security.addProvider(new com.sun.crypto.provider.SunJCE());

        byte key[] = passkey.trim().getBytes();
        DESKeySpec desKeySpec = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey desKey = keyFactory.generateSecret(desKeySpec);

        Cipher desCipher;

        // Create the cipher
        desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

        // initialize base64 handler
        //org.apache.axis.encoding.Base64 base64 = new org.apache.axis.encoding.Base64();

        // decode from base64 first
        byte[] ciphertext = org.apache.axis.encoding.Base64.decode(new String(texttoencrypt.getBytes()));

        // Initialize the same cipher for decryption
        desCipher.init(Cipher.DECRYPT_MODE, desKey);

        // Decrypt the ciphertext
        byte[] cleartext1 = desCipher.doFinal(ciphertext);

        return new String(cleartext1);

    }

    // from http://code.swapnonil.com/2010/10/31/saving-only-real-unicode-characters-in-xml/
    public static String removeInvalidXMLCharacters(String s) {
        StringBuilder out = new StringBuilder();

        int codePoint;
        int i = 0;

        while (i < s.length()) {
            // This is the unicode code of the character.
            codePoint = s.codePointAt(i);
            if ((codePoint == 0x9) || (codePoint == 0xA) || (codePoint == 0xD)
                    || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                    || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                    || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))) {
                out.append(Character.toChars(codePoint));
            }
            i += Character.charCount(codePoint);
        }
        return out.toString();
    }

    public static String removeNonASCII(String s) {
        StringBuilder out = new StringBuilder();

        int codePoint;
        int i = 0;

        while (i < s.length()) {
            // This is the unicode code of the character.
            codePoint = s.codePointAt(i);
            if (codePoint < 128) {
                out.append(Character.toChars(codePoint));
            }
            i += Character.charCount(codePoint);
        }
        return out.toString();
    }

    /**
     * Remove all characters that are valid XML markups.
     * http://www.w3.org/TR/2000/REC-xml-20001006#syntax
     *
     * @param s
     * @return
     */
    public static String removeXMLMarkups(String s) {
        StringBuffer out = new StringBuffer();
        char[] allCharacters = s.toCharArray();
        for (char c : allCharacters) {
            if ((c == '\'') || (c == '<') || (c == '>') || (c == '&') || (c == '\"')) {
                continue;
            } else {
                out.append(c);
            }
        }
        return out.toString();
    }

    /**
    * computes the SHA1 hashcode for the passed byte array.
    *
    * @param  ba byte array.
    * @return SHA1 string.
    */
    public static String computeSHA1(byte[] ba) {
        String hash = null;
        try {

            MessageDigest sha1 = MessageDigest.getInstance("SHA1");
            InputStream is = new ByteArrayInputStream(ba);
            BufferedInputStream bis = new BufferedInputStream(is);

            DigestInputStream dis = new DigestInputStream(bis, sha1);

            while (dis.read() != -1) {
            }
            ;

            byte[] h = sha1.digest();

            Formatter formatter = new Formatter();

            for (byte b : h) {
                formatter.format("%02x", b);
            }

            hash = formatter.toString();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return hash;
    }

}