package ${omPojoPackage};

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

import org.asyrinx.joey.om.Entity;

/** 
 * 
#if( $omDaoPersistance == "hibernate" )
 * 
 * @hibernate.class
 * table="${table.getName()}"
#end
#if ($addTimeStamp)
 * generated by joey-gen on $now
#end
 */
#if ($table.isAbstract())
    #set ($abstract = "abstract")
#end
public $!abstract class ${basePrefix}$table.JavaName implements Serializable, Entity {

## ---------------------- primaryKey ---------------------- 
    /**
     * returns an id that differentiates this object from others
     * of its class.
     */
    public Serializable getPrimaryKey() {
#if ($table.PrimaryKey.size() == 1)
	#set( $pk = ${table.PrimaryKey.get(0)} )
	#set( $pkType = $pk.getJavaType() )
	#set( $pkClass = $typeNameUtils.toClassName( $pkType ) )
	#if( $pkType == $pkClass )
		return get${table.PrimaryKey.get(0).JavaName}();
	#else
        return new $pkClass( get${table.PrimaryKey.get(0).JavaName}() );
	#end
#elseif ($table.PrimaryKey.size() > 1)
        return this;
#else
        return null;
#end
    }
## ---------------------- primaryKey ---------------------- 

## ---------------------- Columns ---------------------- 
#if (!$table.isAlias())
 	## member variables
	#foreach ($col in $table.Columns)
	    #set ( $cfc=$col.JavaName )
	    #set ( $clo=$col.UncapitalisedJavaName )
	    #set ( $cjtype = $col.JavaType )

    /** The value for the $clo field */
	    #if ($stringUtils.isEmpty( $col.getDefaultValueString() ) )
    private $cjtype $clo;
    	#else
    private $cjtype $clo = ${col.getDefaultValueString()};
    	#end

    /**
     * Get the $cfc
     * @return $cjtype
     */
    public $cjtype get${cfc}() {
    	#if( $col.isSingleColumnForeignKey() )
    		#set( $colPropNameLow = $col.getSingleColumnForeignKeyPropertyName() )
    		#set( $colPropName = $stringUtils.capitalize( $colPropNameLow ) )
    		#set( $fk = ${col.getBelongForeignKeys().get(0)} )

			#if( ! $typeNameUtils.isPrimitiveType( $col.getJavaType() ) )
		if (($clo == null) && (this.get${colPropName}() != null)) {
			#elseif( $col.isNumberFieldType() ) 
		if (($clo == 0) && (this.get${colPropName}() != null)) {
			#else
		if (($clo == null) && (this.get${colPropName}() != null)) {
			#end
			##
			#set( $fkLocalCol = $col )
			#set( $fkForeignCol = $fkLocalCol.getForeignColumn( $fk ) )
			#set( $localColType = $fkLocalCol.getJavaType() )
			#set( $foreignPropName = $stringUtils.capitalize($fkForeignCol.getJavaName()) )
			#set( $foreignColType = $fkForeignCol.getJavaType() )

			#if( $typeNameUtils.isPrimitiveType( $localColType ) )
				#if( $typeNameUtils.isPrimitiveType( $foreignColType ) )
			return ${colPropNameLow}.get${foreignPropName}();
				#else
			return ${colPropNameLow}.get${foreignPropName}().${localColType}Value();
				#end
			#else
				#if( $typeNameUtils.isPrimitiveType( $foreignColType ) )
			return new ${localColType}(${colPropNameLow}.get${foreignPropName}());
				#else
			return ${colPropNameLow}.get${foreignPropName}();
				#end
			#end
		} else {
	        return $clo;
		}
		#else
        return $clo;
        #end
    }

    /**
     * Set the value of $cfc
     * @param v new value
     */
    public void set${cfc}($cjtype v) {
	    this.$clo = v;
    }
	#end
#end
## ---------------------- Columns ---------------------- 

## ---------------------- Referring Object ( own foreignKey ) ---------------------- 
#foreach ( $fk in $table.getForeignKeys() )
	#set( $fkTable = $fk.getForeignTableObject() )
	#set( $fkPropNameLow = $fk.getPropertyNameInLocal() )
	#set( $fkPropName = ${stringUtils.capitalize( $fkPropNameLow )} )
	
	private ${fkTable.getJavaName()} $fkPropNameLow = null;

	public ${fkTable.getJavaName()} get${fkPropName}() {
		return this.$fkPropNameLow;
	}
	
	public void set${fkPropName}(${fkTable.getJavaName()} $fkPropNameLow) {
		this.$fkPropNameLow = $fkPropNameLow;
	#foreach($fkLocalColName in $fk.getLocalColumns())
		#set( $fkLocalCol = $table.getColumn($fkLocalColName) )
		#set( $fkForeignColName = $fk.getLocalForeignMapping().get($fkLocalColName) )
		#set( $fkForeignCol = $fkTable.getColumn($fkForeignColName) )
		##
		#set( $localColName = $stringUtils.uncapitalize($fkLocalCol.getJavaName()) )
		#set( $localColType = $fkLocalCol.getJavaType() )
		#set( $foreignPropName = $stringUtils.capitalize($fkForeignCol.getJavaName()) )
		#set( $foreignColType = $fkForeignCol.getJavaType() )
		this.$localColName = ($fkPropNameLow == null) ? ${fkLocalCol.getDefaultValue()} : 
		#if( $typeNameUtils.isPrimitiveType( $localColType ) )
			#if( $typeNameUtils.isPrimitiveType( $foreignColType ) )
			${fkPropNameLow}.get${foreignPropName}();
			#else
			${fkPropNameLow}.get${foreignPropName}().${localColType}Value();
			#end
		#else
			#if( $typeNameUtils.isPrimitiveType( $foreignColType ) )
			new ${localColType}(${fkPropNameLow}.get${foreignPropName}());
			#else
			${fkPropNameLow}.get${foreignPropName}();
			#end
		#end
	#end
	}
	
	public Serializable get${fkPropName}Key(){
	#if($fk.getLocalColumns().size() == 1)
		#set( $fkLocalColName = ${fk.getLocalColumns().get(0)})
		#set( $fkLocalCol = $table.getColumn($fkLocalColName) )
		#set( $localColName = $stringUtils.uncapitalize($fkLocalCol.getJavaName()) )
		#set( $localColType = $fkLocalCol.getJavaType() )
		#if ( $typeNameUtils.isPrimitiveType( $localColType ) )
		return (this.get${fkLocalCol.getJavaName()}() == ${fkLocalCol.getDefaultValue()}) ? null : new ${typeNameUtils.toClassName( $localColType )}(this.get${fkLocalCol.getJavaName()}());
		#else
		return this.get${fkLocalCol.getJavaName()}();
		#end
	#else
		return this;
	#end
	}
	
#end
## ---------------------- Referring Object ( own foreignKey ) ---------------------- 
    
## ---------------------- Referred Objects ( referred foreignKey ) ---------------------- 
#foreach ( $ref in $table.getReferrers() )
	#set( $refTable = ${ref.getTable()} )
	#set( $refPropNameLow = $ref.getPropertyNameInReferred() )
	#set( $refPropName = ${stringUtils.capitalize( $refPropNameLow )} )

    private Set $refPropNameLow = null;
    
	protected void set${refPropName}Internal(Set $refPropNameLow) {
		this.$refPropNameLow = $refPropNameLow;
	}

	protected Set get${refPropName}Internal() {
		if (this.$refPropNameLow == null) {
			this.$refPropNameLow = new HashSet();
		}
		return this.$refPropNameLow;
	}

	public List get${refPropName}() {
		//final List sorted${refPropName} = new ArrayList(get${refPropName}Internal());
		//PropertyComparator.sort(sorted${refPropName}, new MutableSortDefinition("name", true, true));
		//return Collections.unmodifiableList(sorted${refPropName});

		return Collections.unmodifiableList( new ArrayList(get${refPropName}Internal()) );
	}

	#set( $paramNameLow = ${ref.getPropertyNameInReferred( false )} )
	#set( $paramName = ${stringUtils.capitalize( $paramNameLow )} )
	
	/**
	 * Add a ${refTable.getJavaName()} to the List of ${refPropName}.
	 * @param $paramNameLow New ${refTable.getJavaName()} to be added to the List of ${refPropName}
	 */
	public void add${paramName}(${refTable.getJavaName()} $paramNameLow) {
		get${refPropName}Internal().add($paramNameLow);
	}

	/**
	 * remove a ${refTable.getJavaName()} to the List of ${refPropName}.
	 * @param $paramNameLow ${refTable.getJavaName()} to be removed to the List of ${refPropName}
	 */
	public void remove${paramName}(${refTable.getJavaName()} $paramNameLow) {
		get${refPropName}Internal().remove($paramNameLow);
	}
#end    
## ---------------------- Referred Objects ( referred foreignKey ) ---------------------- 


    public String toString() {
#if ($table.PrimaryKey.size() == 1)
        return super.toString();
#else
        return new ToStringBuilder(this)
	#foreach ($pk in $table.PrimaryKey)
            .append("${stringUtils.uncapitalize($pk.getJavaName())}", get${pk.getJavaName()}())
	#end
            .toString();
#end
    }

    public boolean equals(Object other) {
#if ($table.PrimaryKey.size() == 1)
        return super.equals(other);
#else
        if ( !(other instanceof ${table.getJavaName()}) ) 
        	return false;
        ${table.getJavaName()} castOther = (${table.getJavaName()}) other;
        return new EqualsBuilder()
	#foreach ($pk in $table.PrimaryKey)
            .append(this.get${pk.getJavaName()}(), castOther.get${pk.getJavaName()}())
	#end
            .isEquals();
#end
    }

    public int hashCode() {
#if ($table.PrimaryKey.size() == 1)
        return super.hashCode();
#else
        return new HashCodeBuilder()
	#foreach ($pk in $table.PrimaryKey)
            .append(get${pk.getJavaName()}())
	#end
            .toHashCode();
#end
    }
    
    
	public boolean equalsInData(Object other) {
		if (other instanceof ${basePrefix}$table.JavaName) {
			final ${basePrefix}$table.JavaName obj = (${basePrefix}$table.JavaName) other;
			return new EqualsBuilder()
#foreach ($col in $table.Columns)
				.append(this.get${col.getJavaName()}(), obj.get${col.getJavaName()}())
#end
				.isEquals();
		} else {
			return false;
		}
	}

	public boolean equalsInProperties(Object other) {
		if (other instanceof ${basePrefix}$table.JavaName) {
			final ${basePrefix}$table.JavaName obj = (${basePrefix}$table.JavaName) other;
			return equalsInData(other) &&
				new EqualsBuilder()
#foreach ( $ref in $table.getReferrers() )
	#set( $refTable = ${ref.getTable()} )
	#set( $refPropNameLow = $ref.getPropertyNameInReferred() )
	#set( $refPropName = ${stringUtils.capitalize( $refPropNameLow )} )
				.append(this.get${refPropName}(), obj.get${refPropName}())
#end
				.isEquals();
		} else {
			return false;
		}
	}
}
