<#macro single_line><#local captured><#nested></#local>${ captured?replace("^\\s+|\\s+$|\\n|\\r", "", "rm") }</#macro>
<#macro getter_setter classClass field fieldName>
    /**
    * Obtém ${fieldName}
    * return ${fieldName}
    * @generated
    */
    <#if field.securityAnnotation != "">
    ${field.securityAnnotation}
    </#if>
    public ${field.type} get${fieldName?cap_first}() {
        return this.${fieldName};
    }

    /**
    * Define ${fieldName}
    * @param ${fieldName} ${fieldName}
    * @generated
    */
    public ${classClass.name} set${fieldName?cap_first}(${field.type} ${fieldName}) {
        <#if field.isEncryption() && field.getPasswordPolicy() != "full">
        this.${fieldName} = ${fieldName}.startsWith(ENCRYPT) ? ${fieldName} : new BCryptPasswordEncoder().encode(${fieldName});
        <#else>
        this.${fieldName} = ${fieldName};
        </#if>
        return this;
    }
</#macro>

package ${entityPackage}<#if subPackage??>.${subPackage}</#if>;

import java.io.*;
import jakarta.persistence.*;
import java.util.*;
import jakarta.xml.bind.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonFilter;
import cronapi.rest.security.CronappSecurity;
<#if clazz.rest>
import cronapi.swagger.CronappSwagger;
</#if>
<#if clazz.hasRowVersion() || clazz.hasXML() || clazz.hasUUID()>
import org.eclipse.persistence.annotations.Convert;
import org.eclipse.persistence.annotations.Converter;
</#if>
<#if clazz.hasRowVersion()>
import cronapi.database.VersionConverter;
</#if>
<#if clazz.hasUUID()>
import cronapi.database.UUIDConverter;
</#if>
<#if clazz.hasUseOuterJoin()?? && clazz.hasUseOuterJoin()>
import org.eclipse.persistence.annotations.JoinFetch;
import org.eclipse.persistence.annotations.JoinFetchType;
</#if>
<#if clazz.hasXML()>
import cronapi.database.ByteConverter;
</#if>
<#if clazz.hasNotEmpty()>
    import jakarta.validation.constraints.NotEmpty;
</#if>
<#assign hasCloudStorage = clazz.hasCloudStorage()>
<#if hasCloudStorage>
    import cronapi.CronapiCloud;
</#if>
<#if clazz.hasSearchable()>
    import cronapi.CronapiSearchable;
</#if>
<#if clazz.hasFileDataBase()>
    import cronapi.CronapiByteHeaderSignature;
</#if>
<#if clazz.hasEncryption()>
  <#if clazz.hasStrongPassword()>
import cronapp.framework.persistence.ValidPassword;
import cronapp.framework.persistence.ValidPasswords;
import cronapp.framework.persistence.PasswordEncoderListener;
  </#if>
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
</#if>
<#list clazz.imports as import>
    import ${import};
</#list>
<#if subPackage??>import ${entityPackage}.*;</#if>
<#list clazz.subPackageToImport as subPackageToImport>
    <#if subPackage?? && subPackageToImport != subPackage >
        import ${entityPackage}.${subPackageToImport}.*;
    </#if>
</#list>

<#if (clazz.multitenantClass)>
import org.eclipse.persistence.annotations.*;
</#if>

import cronapp.framework.core.persistence.*;

/**
* Classe que representa a tabela <#if tableName??>${tableName}<#else>${clazz.name?upper_case}</#if>
* @generated
*/
@jakarta.persistence.Entity
<#if clazz.hasCompositeKey()>
@IdClass(${clazz.name + 'PK'}.class)
</#if>
@jakarta.persistence.Table(name = "\"<#if tableName??><#if persistenceProvider == "oracle">${tableName?upper_case}<#else>${tableName}</#if><#else>${clazz.name?upper_case}</#if>\""<#if schemeName??>, schema="\"<#if persistenceProvider == "oracle">${schemeName?upper_case}<#else>${schemeName}</#if>\""</#if><#if (clazz.indexFields?size > 0)> ,indexes={<#list clazz.indexFields as field>@Index(name="IDX_<#if tableName??>${tableName}<#else>${clazz.name?upper_case}</#if>_${field.dbFieldName?upper_case}", columnList="${field.dbFieldName}")<#if field?has_next>, </#if></#list>}</#if>)
<#-- depreciated unique composition
<#if (clazz.fieldsUniqueKey?size > 0)>
    ,uniqueConstraints=@UniqueConstraint(name="UNQ_
    <#if tableName??>
        ${tableName}
    <#else>
        ${clazz.name?upper_case}
    </#if>
    _0", columnNames={
    <#list clazz.fieldsUniqueKey as field>
        "${field.dbFieldName}"
        <#if field?has_next>
            ,
        </#if>
    </#list>
    })
</#if>
-->
@XmlRootElement
<#if clazz.rest>
@CronappSecurity<#if restSecurityDescription??>(${restSecurityDescription})</#if>
</#if>
<#if clazz.swagger>
@CronappSwagger
</#if>
<#if (clazz.multitenantClass)>
@Multitenant(MultitenantType.SINGLE_TABLE)
    <#if (clazz.multitententFields?size > 1)>
@TenantDiscriminatorColumns({
    </#if>
    <#list clazz.multitententFields as field>
@TenantDiscriminatorColumn(name = "${field.dbFieldName?replace("\"", "\\\"")}", contextProperty = "${field.multitenantContext}")<#if field_has_next>,</#if>
    </#list>
    <#if (clazz.multitententFields?size > 1)>
})
    </#if>
</#if>
@JsonFilter("${entityPackage}<#if subPackage??>.${subPackage}</#if>.${clazz.name}")
<#if clazz.listeners??>
@EntityListeners(${clazz.listeners})
</#if>
<#if clazz.hasRowVersion()>
@Converter(
  name="version",
  converterClass=VersionConverter.class
)
</#if>
<#if clazz.hasXML()>
@Converter(
  name="bytes",
  converterClass=ByteConverter.class
)
</#if>
<#if clazz.hasUUID()>
@Converter(
  name="uuid",
  converterClass=UUIDConverter.class
)
</#if>
<#if clazz.hasStrongPassword() && clazz.hasEncryption()>
@ValidPasswords({
    <#list clazz.fields as field>
        <#if field.isEncryption() && field.getPasswordPolicy() == "full">
    @ValidPassword(passwordProperty = "${field.name}", passwordHistoryProperty = "${field.name}History"),
        </#if>
    </#list>
})
</#if>
<#if clazz.role == "AssociationClass">
    <#assign cronappTableRole = "CronappTableRole.ASSOCIATION_CLASS">
<#elseif clazz.role == "Class">
    <#assign cronappTableRole = "CronappTableRole.CLASS">
<#else>
    <#assign cronappTableRole = "CronappTableRole.AUTO">
</#if>
@CronappTable(role=${cronappTableRole})
public class ${clazz.name} implements Serializable {
<#if clazz.hasEncryption()>
    /**
    * Variável privada para verificação da criptofrafia
    *
    * @generated
    */
    private static final String ENCRYPT = "$2a$10$";
</#if>
    /**
    * UID da classe, necessário na serialização
    * @generated
    */
    private static final long serialVersionUID = 1L;
<#list clazz.fields as field>
    <#if field.primaryKey>
        <#assign name = "${field.name}">

    /**
    * @generated
    */
    @Id
        <#if field.generationType?? && field.generationType == "Identity">
            <#if persistenceProvider == "mysql">
    @GeneratedValue(strategy = GenerationType.AUTO)
            <#else>
    @GeneratedValue(strategy = GenerationType.IDENTITY)
            </#if>
        </#if>
    <#if (field.isUUID())!false>
    @Convert("uuid")
    </#if>
    <#if field.isNotEmpty()>
    @NotEmpty
    </#if>
        <#if field.isVersion()>
    @Version
        <#elseif field.isDate()>
    @Temporal(TemporalType.DATE)
        <#elseif field.isTime()>
    @Temporal(TemporalType.TIME)
        <#elseif field.isTimestamp()>
    @Temporal(TemporalType.TIMESTAMP)
        </#if>
        <#if (field.relationNames?size == 1)>
            <#list field.relationNames?keys as key>
                <#if key??>
    @JoinColumn(name="${(key)?replace("\"", "\\\"")}", nullable = ${field.nullable?c}, referencedColumnName = "${field.relationNames[key]?replace("\"", "\\\"")}", insertable=${field.insertable?c}, updatable=${field.updatable?c})
                </#if>
            </#list>
        <#elseif (field.relationNames?size > 1)>
            <#assign i= field.relationNames?size>
    @JoinColumns({
            <#list field.relationNames?keys as key>
                <#if key??>
    @JoinColumn(name="${(key)?replace("\"", "\\\"")}", nullable = ${field.nullable?c}, referencedColumnName = "${field.relationNames[key]?replace("\"", "\\\"")}", insertable=${field.insertable?c}, updatable=${field.updatable?c})
                    <#if (i>1)>,</#if>
                </#if>
                <#assign i = i-1>
            </#list>
    })
        <#else>
    <#if field.columnDefinition?? && field.columnDefinition == "TEXT" && persistenceProvider?upper_case == "ORACLE">
    @Lob
    </#if>
    @CronappColumn(attributeType="${field.attributeType}"<#if field.label?has_content>, label="${field.label}"</#if><#if field.mask?has_content>, mask="${field.mask}"</#if><#if field.searchable>, searchable = true</#if><#if field.defaultValue?has_content>, defaultValue = "${field.defaultValue?j_string}"</#if>)
    @Column(name = "${field.dbFieldName?replace("\"", "\\\"")}", nullable = ${field.nullable?c}<#if !field.primaryKey>, unique = ${field.unique?c}</#if><#if field.length??>, length=${field.length?c}</#if><#if field.precision??>, precision=${field.precision?c}</#if><#if field.scale??>, scale=${field.scale?c}</#if>, insertable=${field.insertable?c}, updatable=${field.updatable?c}<#if field.columnDefinition?? && (field.columnDefinition != "TEXT" || persistenceProvider?upper_case != "ORACLE")>, columnDefinition = "${field.columnDefinition}"</#if>)
        </#if>
        ${field.modifier} <#if field.arrayRelation>${field.type}<#else>${field.type}</#if> ${name}<#if field.defaultValue?has_content> = ${field.defaultValue}<#elseif field.primaryKey && field.generationType?? && field.generationType == "UUID"> = UUID.randomUUID().toString().toUpperCase()</#if>;
    </#if>
</#list>
<#list clazz.fields as field>
    <#if !field.primaryKey>

    /**
    * @generated
    */
        <#if (field.rowVersion)!false>
    @Convert("version")
        </#if>
        <#if (field.isUUID())!false>
    @Convert("uuid")
        </#if>
        <#if field.isNotEmpty()>
    @NotEmpty
        </#if>
        <#if (field.XML)!false>
    @Convert("bytes")
        </#if>
        <#if field.relation>
    @OneToOne
        <#elseif field.reverseRelation>
    @ManyToOne
        </#if>
        <#if (field.relationNames?size == 1)>
            <#list field.relationNames?keys as key>
                <#if key??>
    @JoinColumn(name="${(key)?replace("\"", "\\\"")}", nullable = ${field.nullable?c}, referencedColumnName = "${field.relationNames[key]?replace("\"", "\\\"")}", insertable=${field.insertable?c}, updatable=${field.updatable?c}<#if field.cascade>, foreignKey = @ForeignKey(name = "<#if tableName??>${tableName?replace("\"", "\\\"")}<#else>${(clazz.name?upper_case)?replace("\"", "\\\"")}</#if>_${(key?upper_case)?replace("\"", "\\\"")}_${field.dbTableRelationClazz?replace("\"", "\\\"")}_${(field.relationNames[key]?upper_case)?replace("\"", "\\\"")}", foreignKeyDefinition = "FOREIGN KEY (${(key)?replace("\"", "\\\"")}) REFERENCES ${field.dbTableRelationClazz} (${field.relationNames[key]?replace("\"", "\\\"")}) ON DELETE CASCADE")<#elseif field.fkName?has_content>, foreignKey = @ForeignKey(name = "${field.fkName?replace("\"", "\\\"")}", foreignKeyDefinition = "FOREIGN KEY (${(key)?replace("\"", "\\\"")}) REFERENCES ${field.dbTableRelationClazz} (${field.relationNames[key]?replace("\"", "\\\"")})")</#if>)
                </#if>
            </#list>
        <#elseif (field.relationNames?size > 1)>
            <#assign i= field.relationNames?size>
    @JoinColumns({
            <#list field.relationNames?keys as key>
                <#if key??>
    @JoinColumn(name="${(key)?replace("\"", "\\\"")}", nullable = ${field.nullable?c}, referencedColumnName = "${field.relationNames[key]?replace("\"", "\\\"")}", insertable=${field.insertable?c}, updatable=${field.updatable?c}<#if field.fkName?has_content>, foreignKey = @ForeignKey(name = "${field.fkName?replace("\"", "\\\"")}", foreignKeyDefinition = "FOREIGN KEY (${(key)?replace("\"", "\\\"")}) REFERENCES ${field.dbTableRelationClazz} (${field.relationNames[key]?replace("\"", "\\\"")})")</#if>)
                    <#if (i>1)>,</#if>
                </#if>
                <#assign i = i-1>
            </#list>
    })
        <#elseif field.arrayRelation>
    @OneToMany(fetch = FetchType.LAZY, mappedBy="${field.mappedBy?replace("\"", "\\\"")}", insertable=${field.insertable?c}, updatable=${field.updatable?c})
        <#else>
            <#if field.transient>
    @Transient
            <#else>
                <#if field.isVersion()>
    @Version
                <#elseif field.isDate()>
    @Temporal(TemporalType.DATE)
                <#elseif field.isTime()>
    @Temporal(TemporalType.TIME)
                <#elseif field.isTimestamp()>
    @Temporal(TemporalType.TIMESTAMP)
                </#if>
    <#if field.columnDefinition?? && field.columnDefinition == "TEXT" && persistenceProvider?upper_case == "ORACLE">
    @Lob
    </#if>
    @CronappColumn(attributeType="${field.attributeType}"<#if field.label?has_content>, label="${field.label}"</#if><#if field.mask?has_content>, mask="${field.mask}"</#if><#if field.searchable>, searchable = true</#if><#if field.defaultValue?has_content>, defaultValue = "${field.defaultValue?j_string}"</#if>)
    @Column(name = "${field.dbFieldName?replace("\"", "\\\"")}", nullable = ${field.nullable?c}<#if !field.primaryKey>, unique = ${field.unique?c}</#if><#if field.length??>, length=${field.length?c}</#if><#if field.precision??>, precision=${field.precision?c}</#if><#if field.scale??>, scale=${field.scale?c}</#if>, insertable=${field.insertable?c}, updatable=${field.updatable?c}<#if field.columnDefinition?? && (field.columnDefinition != "TEXT" || persistenceProvider?upper_case != "ORACLE")>, columnDefinition = "${field.columnDefinition}"</#if>)
            </#if>
        </#if>
        <#if field.getUseOuterJoin()>
    @JoinFetch(JoinFetchType.OUTER)
        </#if>
        <#if (field.ignore)>
    @JsonIgnore
        </#if>
        <#if field.isCloudStorage()>
    @CronapiCloud(type = "${field.getStorageType()}", value="${field.getStorageKey()}", id="${field.getStorageId()}", secret="${field.getStorageSecret()}", regionAWS="${field.getRegionAWS()}")
        </#if>
        <#if field.isFileDataBase()>
    @CronapiByteHeaderSignature
        </#if>
        <#if field.isSearchable()>
    @CronapiSearchable
        </#if>
        ${field.securityAnnotation}
        ${field.modifier} <#if field.arrayRelation>${field.type}<#else>${field.type}</#if> ${field.name}<#if field.defaultValue?has_content> = ${field.defaultValue}</#if>;
    </#if>

    <#if field.isEncryption() && field.getPasswordPolicy() == "full">
    /**
    * @generated
    */
    <@single_line>@Column(name = "${field.dbFieldName?replace("\"", "\\\"")}_history"
        <#if !field.insertable>, insertable = ${field.insertable?c}</#if>
        <#if !field.updatable>, updatable = ${field.updatable?c}</#if>
    )</@single_line>
    ${field.modifier} ${field.type} ${field.name}History;
    </#if>
</#list>

    /**
    * Construtor
    * @generated
    */
    public ${clazz.name}(){
    }

<#list clazz.fields as field>
    <@getter_setter clazz field "${field.name}" />
    <#if field.isEncryption() && field.getPasswordPolicy() == "full">
    <@getter_setter clazz field "${field.name}History" />
    </#if>
</#list>

    /**
    * @generated
    */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
${clazz.name} object = (${clazz.name})obj;
<#list clazz.fields as field>
    <#if field.primaryKey>
        <#assign name = "${field.name}">
        if (${name} != null ? !${name}.equals(object.${name}) : object.${name} != null) return false;
    </#if>
</#list>
        return true;
    }

    /**
    * @generated
    */
    @Override
    public int hashCode() {
        int result = 1;
<#list clazz.fields as field>
    <#if field.primaryKey && !field.isTypePrimitive()>
        <#assign name = "${field.name}">
        result = 31 * result + ((${name} == null) ? 0 : ${name}.hashCode());
    </#if>
</#list>
        return result;
    }

}
