/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */


package org.ow2.jonas.generators.genic;


import java.lang.reflect.Field;

import org.ow2.jonas.deployment.ejb.FieldDesc;
import org.ow2.jonas.lib.ejb21.JavaType;
import org.ow2.jonas.lib.ejb21.jorm.JormType;



/**
 * This class is the "Velocity context" for a container managed persistence bean's field
 * used in the Velocity Template.
 * @author Helene Joanin : Initial developer
 */

public class VcField {

    /**
     * Name of the cmp field
     */
    private String  mName = null;
    /**
     * Type's name of the cmp field
     */
    private String  mTypeName = null;
    /**
     * Is the field composes the primary key
     */
    private boolean isPrimaryKey = false;
    /**
     * Is a cmp field version 1 (or version 2)
     */
    private boolean mIsCmp1 = false;
    /*
     *  For Cmp1 only
     */
    /**
     * String representation of the java default value (ie 0 for int, null for object, ...)
     */
    private String  mDefaultValue = null;
    /**
     * SQL type's name of the cmp field
     */
    private String  mSqlTypeName = null;
    /**
     * SQL getter method's name
     */
    private String  mSqlGetMethod = null;
    /**
     * SQL setter method's name
     */
    private String  mSqlSetMethod = null;
    /**
     * Is the type of the cmp field is primitive
     */
    private boolean hasNotPrimitiveType = false;
    /**
     * Is the type of the cmp field is java.math.BigInteger
     */
    private boolean hasBigIntegerType = false;
    /**
     * Is the type of the cmp field is Serializable
     */
    private boolean hasSerializableType = false;
    /**
     * Is the type of the cmp field is a java.lang type except java.lang.String
     */
    private boolean hasJavaLangTypeExceptString = false;
    /*
     * For CMP2 only
     */
    /**
     * JORM type name of the cmp field
     */
    private String  jormTypeName = null;
    /**
     * Is the cmp field must be converted between the memory representation and the storage representation
     */
    private boolean mustBeConvert = false;
    /**
     * Convertion class name
     */
    private String  convertClassName = null;

    /**
     * VcField constructor
     * @param mName name of the cmp field
     * @param fType type of the cmp field
     * @param fd field descriptor of the cmp field
     * @param isCmp1 true if it's a cmp version 1 field, false if it's a cmp version 2 field.
     */
    public VcField(String mName, Class fType, FieldDesc fd, boolean isCmp1) {
        mIsCmp1 = isCmp1;
        this.mName = mName;
        mTypeName = JavaType.getName(fType);
        isPrimaryKey = fd.isPrimaryKey();
        mDefaultValue = JavaType.getDefaultValue(fType);
        if (mIsCmp1) {
            // CMP 1
            mSqlTypeName = JavaType.getSQLType(fType);
            mSqlGetMethod = JavaType.getSQLGetMethod(fType);
            mSqlSetMethod = JavaType.getSQLSetMethod(fType);
            hasNotPrimitiveType = !fType.isPrimitive();
            hasBigIntegerType = fType.equals(java.math.BigInteger.class);
            hasSerializableType = "setSerializable".equals(mSqlSetMethod)
                && "getSerializable".equals(mSqlGetMethod);
            hasJavaLangTypeExceptString = false;
            if (fType.getPackage() != null) {
                if ("java.lang".equals(fType.getPackage().getName())
                    && !java.lang.String.class.equals(fType)) {
                    hasJavaLangTypeExceptString = true;
                }
            }
        } else {
            // CMP 2
            jormTypeName = JormType.getPType(fType, isPrimaryKey).getJavaName();
            if (fType.equals(java.sql.Date.class)) {
                mustBeConvert = true;
                convertClassName = "org.ow2.jonas.lib.ejb21.sql.SqlDateFieldMapping";
            } else if (fType.equals(java.sql.Time.class)) {
                mustBeConvert = true;
                convertClassName = "org.ow2.jonas.lib.ejb21.sql.SqlTimeFieldMapping";
            } else if (fType.equals(java.sql.Timestamp.class)) {
                mustBeConvert = true;
                convertClassName = "org.ow2.jonas.lib.ejb21.sql.SqlTimestampFieldMapping";
            } else if (isPrimaryKey && fType.equals(Float.class)) {
                // JORM does not support Float for the primary key, we must so convert it
                mustBeConvert = true;
                convertClassName = "org.ow2.jonas.lib.ejb21.jorm.FloatPkFieldMapping";
            }
        }
    }

    /**
     * VcField contructor for cmp field version 1
     * @param field java field descriptor of the cmp field
     * @param fd field descriptor of the cmp field
     */
    VcField(Field field, FieldDesc fd) {
        this(field.getName(), field.getType(), fd, true);
    }

    /**
     * VcField onstructor for cmp field version 2
     * @param fd field descriptor of the cmp field
     */
    VcField(FieldDesc fd) {
        this(fd.getName(), fd.getFieldType(), fd, false);
    }

    /**
     * @return the name of the cmp field
     */
    public String getName() {
        return mName;
    }

    /**
     * @return the name, with the first letter capitalized, of the cmp field
     */
    public String getNameUpperFirst() {
        return Character.toUpperCase(mName.charAt(0)) + mName.substring(1);
    }

    public String jormGetter() {
        return "paGet" + getNameUpperFirst();
    }

    public String jormSetter() {
        return "paSet" + getNameUpperFirst();
    }

    /**
     * @return the name of the getter method of the cmp field
     */
    public String getGetterName() {
        return "get" + Character.toUpperCase(mName.charAt(0)) + mName.substring(1);
    }

    /**
     * @return the name of the setter method of the cmp field
     */
    public String getSetterName() {
        return "set" + Character.toUpperCase(mName.charAt(0)) + mName.substring(1);
    }

    /**
     * @return the type name of the cmp field
     */
    public String getTypeName() {
        return mTypeName;
    }

    /**
     * @return true if the cmp field composes the primary key
     */
    public boolean isPrimaryKey() {
        return isPrimaryKey;
    }

    /*
     * CMP version 1 only
     */
    /**
     * @return the string representation of the java default value for the cmp field (ie "0 "for int, "null" for object ...)
     */
    public String getDefaultValue() {
        return mDefaultValue;
    }

    /**
     * @return the SQL type name of the cmp field
     */
    public String getSqlTypeName() {
        return mSqlTypeName;
    }

    /**
     * @return the SQL getter method name for the cmp field
     */
    public String getSqlGetMethod() {
        return mSqlGetMethod;
    }

    /**
     * @return the SQL setter method name for the cmp field
     */
    public String getSqlSetMethod() {
        return mSqlSetMethod;
    }

    /**
     * @return true if the type of the cmp field is not a java primitive type
     */
    public boolean hasNotPrimitiveType() {
        return hasNotPrimitiveType;
    }

    /**
     * @return true if the type of the cmp field is java.math.BigInteger
     */
    public boolean hasBigIntegerType() {
        return hasBigIntegerType;
    }

    /**
     * @return true of the type of the cmp field is Serializable
     */
    public boolean hasSerializableType() {
        return hasSerializableType;
    }

    /**
     * @return true if the type of the cmp type is a java.lag type except java.lang.String
     */
    public boolean hasJavaLangTypeExceptString() {
        return hasJavaLangTypeExceptString;
    }

    /*
     * CMP version 2 only
     */
    /**
     * @return the JORM type name of the cmp field
     */
    public String getJormTypeName() {
        return jormTypeName;
    }

    /**
     * @return true if a conversion must be dome between the memory representation and the storage representation for the cmp field
     */
    public boolean isMustBeConvert() {
        return mustBeConvert;
    }

    /**
     * @return the class name of for the convertion between the memory representation and the storage representation for the cmp field
     */
    public String getConvertClassName() {
        return convertClassName;
    }

    /**
     * @return a string representation of the VcField for debug use
     */
    public String toString() {
        StringBuffer ret = new StringBuffer();
        ret.append("\n    Name                 = " + getName());
        ret.append("\n    isPrimaryKey         = " + isPrimaryKey());
        ret.append("\n    NameUpperFirst       = " + getNameUpperFirst());
        ret.append("\n    GetterName           = " + getGetterName());
        ret.append("\n    SetterName           = " + getSetterName());
        ret.append("\n    TypeName             = " + getTypeName());
        ret.append("\n    DefaultValue         = " + getDefaultValue());
        if (mIsCmp1) {
            ret.append("\n    SqlTypeName          = " + getSqlTypeName());
            ret.append("\n    SqlGetMethod         = " + getSqlGetMethod());
            ret.append("\n    SqlSetMethod         = " + getSqlSetMethod());
            ret.append("\n    hasNotPrimitiveType  = " + hasNotPrimitiveType());
            ret.append("\n    hasBigIntegerType    = " + hasBigIntegerType());
            ret.append("\n    hasSerializableType  = " + hasSerializableType());
            ret.append("\n    hasJavaLangTypeExceptString = " + hasJavaLangTypeExceptString());
        } else {
            ret.append("\n    JormTypeName         = " + getJormTypeName());
            ret.append("\n    MustBeConvert        = " + isMustBeConvert());
            ret.append("\n    ConvertClassName     = " + getConvertClassName());
        }
        return (ret.toString());
    }

}
