<%
/*
Note: The contents of this file will be directly overwritten when EZDML is upgraded. Instead of modifying this file directly, copy the file to a new name and modify the new file.

注意：程序升级时会直接覆盖此文件内容，请不要直接修改此文件，如果需要请将此文件复制到新名称，然后对新文件进行修改。

2022-3-27: 第一版发布

*/

var parentPkgName=GetGParamValue('EZGEN_ROOT_PKGNAME'); //上级包名
if(!parentPkgName)parentPkgName='com.ezdml.codegen.ezdmlcodegendemo';

var tb=curTable; //当前表
var ClsName=AutoCapProc(tb.name,'ClassName'); //类名（驼峰命名，首字母大写）
var dispName=tb.UIDisplayName; //逻辑显示名

var fds=tb.metaFields;

%>package ${parentPkgName}.${AutoCapProc(curModel.name,'JavaPackageName')}.${AutoCapProc(tb.name,'JavaPackageName')};

/*
 * Copyright © ${FormatDateTime('yyyy',_date())} xxx.xx All rights reserved.
 * Author: xxx (xx@xx.com)
 * Generated by EZDML ${DateTimeToStr(_now())}

${tb.describe}

 */

import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.*;
import java.util.*;
<%
  //添加外键引用类，并判断主键是否引用了其它表
  var importTbs={};
  var rfTbName='';
  //遍历所有字段
  for(var k=0; k<fds.count; k++) 
  { //字段循环开始
    var fd = fds.getItem(k); //取第k个字段
    if(!fd.isPhysicalField()) //判断字段是否物理字段
      continue;
    if(fd.keyFieldType=='cfktId' || fd.keyFieldType=='cfktRid'){ //外键？
      var cf=fd.getRelateTableField(); //外键引用的表字段是否存在
      if(cf){
        var rtb=fd.getRelateTableObj();
        if(rtb.name==tb.name) //引用了自己？
          continue;
        //要在同一个模型才添加引用
        if(!curModel.tables.itemByName(rtb.name, false))
          continue;
        if(fd.keyFieldType=='cfktId')
          if(!rfTbName)
            rfTbName=rtb.name;
        importTbs[rtb.name]=rtb.name;
      }
    }
  }

  //判断主键是否引用了其它表，如果有，则继承
  var extCls='';
  if(rfTbName){
    extCls='extends '+AutoCapProc(rfTbName,'ClassName')+' ';
    curOut.add('import lombok.EqualsAndHashCode;');
  }

  
  //获取引用了自己的所有子表
  var hasOneToOne=false; //是否有一对一引用
  var refTbs={}; //记录关联表名和关联字段名
  var rstr=tb.getOneToManyInfo(true);//+"\n"+tb.getManyToManyInfo()
  var rinfos=rstr.split("\n");
  //遍历关联表
  for(var j=0; j<rinfos.length; j++)
  {
    var tt = rinfos[j];
    if(!tt)
      continue;
    var po=tt.indexOf(".");
    if(po<=0)
      continue;
    var vtbn=tt.substring(0,po);
    if(vtbn==tb.name) //忽略自己
      continue;
    var cmtb=curModel.tables.itemByName(vtbn, false); //必须在同一个模型中
    if(!cmtb)
      continue;
    tt=tt.substr(po+1);
    po=tt.indexOf(':');
    if(po<=0)
      continue;
    var rfd=tt.substring(0,po);
    if(rfd){  //记录关联表名和关联字段名，并增加引用
      refTbs[vtbn]=rfd;
      importTbs[vtbn]=vtbn;
      var xfd=cmtb.metaFields.itemByName(rfd);
      if(xfd)
        if(xfd.keyFieldType=='cfktId'){ //关联字段恰好是主键，说明会一对一地继承本对象
          hasOneToOne=true;
        }
    }
  }

  //输出所有引入表
  for(var rtbName in importTbs){
    curOut.add('import '+parentPkgName+'.'+AutoCapProc(curModel.name,'JavaPackageName')+'.'+AutoCapProc(rtbName,'JavaPackageName')+'.'+AutoCapProc(rtbName,'ClassName')+';');
  }
  
%>

@Entity
@Data
@ApiModel("${dispName}")
@AllArgsConstructor
@NoArgsConstructor<% if(extCls){ %>
@EqualsAndHashCode(callSuper=true)<% } 
if(hasOneToOne){ %>
@Inheritance(strategy = InheritanceType.JOINED)<% } %>
public class ${ClsName} ${extCls}{

<%
         
  if(!extCls)
    if(!tb.getPrimaryKeyField()){
      //没有主键的，手工加一个ID
      fout('//注意：本对象没有主键不符合要求，EZDML补了一个ID主键，避免运行出错');
      fout('@ApiModelProperty(value="编号", required=true, example="123")');
      fout('@Id');
      fout('@GeneratedValue');
      fout('@NotEmpty');
      fout('@Column(nullable=false)');
      fout('private long id;');
      fout('');
    }

  //遍历所有字段
  for(var k=0; k<fds.count; k++) 
  { //字段循环开始
    var fd = fds.getItem(k); //取第k个字段
    if(!fd.isPhysicalField()) //判断字段是否物理字段
      continue;

    //继承的子类，不输出ID
    if(extCls)
      if(fd.name.toLowerCase()=='id')
        continue;

    var fdn=AutoCapProc(fd.name,'FieldName');
    //输出名称
    var mp='value="'+fd.getLabelText()+'"';
    if(fd.isRequired()){
      mp=mp+', required=true';
    }
    if(fd.dataType=='cfdtString' || fd.dataType=='cfdtDate')
      mp=mp+', example="' + fd.genDemoData() +'"';
    else if(fd.dataType=='cfdtInteger' || fd.dataType=='cfdtFloat')
      mp=mp+', example="123"';
    else if(fd.dataType=='cfdtEnum')
      mp=mp+', example="1"';
    else if(fd.dataType=='cfdtBool')
      mp=mp+', example="true"';

    var tp=getFieldJavaType(fd); //数据类型
    if(fd.keyFieldType=='cfktId'){ //主键？
      fout('@Id');
      if(tp=='int'){
        fout('@GeneratedValue');
        tp='long';
      } else {
        fout('@GeneratedValue(generator="sys_uuid")');
        fout('@GenericGenerator(name="sys_uuid", strategy="uuid")');
      }
    }
    

    if(fd.keyFieldType=='cfktRid'){ //外键？
      var cf=fd.getRelateTableField(); //外键引用的表字段是否存在
      if(cf){
        var rtb=fd.getRelateTableObj();
        //不在同一个模型中，注释掉
        var bSameModel=true;
        if(!curModel.tables.itemByName(rtb.name, false))
          bSameModel=false;
        if(!bSameModel)
          fout('/*');
        //存在时，输出外键信息
        fout('@ApiModelProperty('+mp+')');
        if(fd.isRequired())
          fout('@NotEmpty');
        var rtp='@ManyToOne';
        if(fd.indexType=='cfitUnique') //唯一?
        {
          rtp='@OneToOne';
        }
        var s=rtp+'(targetEntity='+AutoCapProc(rtb.name,'ClassName')+'.class)';
        fout(s); //输出
        var s='@JoinColumn(name="'+fd.name+'", referencedColumnName="'+cf.name+'")';
        fout(s); //输出

        var pname=AutoCapProc(fd.name,'FieldName');
        //如果以ID结尾，去掉ID
        pname=removeFieldSubfixId(pname);
        //输出引用类名
        fout('private '+AutoCapProc(rtb.name,'ClassName')+' '+pname+';');
        if(!bSameModel)
          fout('*/');
        fout('');
        //不再输出字段信息
        continue;
      }
    }

    fout('@ApiModelProperty('+mp+')');
    if(fd.isRequired())
      fout('@NotEmpty');
    var cs='';
    if(fdn.toLowerCase()!=fd.name.toLowerCase())
      cs='name="'+fd.name+'"';
    if(tp=='String' && fd.dataLength>0) //长度
      cs+=(cs==''?'':', ')+'length='+fd.dataLength;
    if(!fd.nullable) //可为空？
      cs+=(cs==''?'':', ')+'nullable=false';
    if(fd.indexType=='cfitUnique') //唯一索引
      cs+=(cs==''?'':', ')+'unique=true';
    if(cs){
      fout('@Column('+cs+')');
    }
    fout('private '+tp+' '+fdn+';');
    fout('');
  }
 

  //输出所有引用自己的子表
  for(var rtbName in refTbs){
    var rClsName=AutoCapProc(refTbs[rtbName],'FieldName');
    rClsName=removeFieldSubfixId(rClsName);
    var fd=tb.fieldOfChildTable(rtbName); //默认不输出子表的内容，除非在表里手工添加List字段
    if(fd){
      var fdn=AutoCapProc(fd.name,'FieldName');
      fout('@ApiModelProperty(value="'+fd.getLabelText()+'")');
      fout('@OneToMany(targetEntity='+AutoCapProc(rtbName,'ClassName')+'.class, mappedBy="'+rClsName+'", fetch=FetchType.LAZY, cascade=CascadeType.REFRESH)');
      fout('private List<'+AutoCapProc(rtbName,'ClassName')+'> '+AutoCapProc(fdn,'FieldName')+';');
    } else {
      fout('/*');
      fout('@ApiModelProperty(hidden=true)');
      //fout('@JsonIgnore');
      fout('@OneToMany(targetEntity='+AutoCapProc(rtbName,'ClassName')+'.class, mappedBy="'+rClsName+'", fetch=FetchType.LAZY, cascade=CascadeType.REFRESH)');
      fout('private List<'+AutoCapProc(rtbName,'ClassName')+'> '+AutoCapProc(rtbName,'FieldName')+'List;');
      fout('*/');
    }
    fout('');
  }


function removeFieldSubfixId(pname){
  var len=pname.length;
  if(pname.substring(len-2,len)=='Id')
    pname=pname.substring(0,len-2);
  return pname;
}

function getFieldJavaType(fd) {
  //获取字段类型对应的JAVA类型
  var cfType=fd.dataType;
  if(cfType.indexOf("cfdt")==0){
    var res= cfType.substr(4);
    if(res=="Integer")
      return "int";
    if(res=="Float")
      return "double";
    if(res=="Bool")
      return "boolean";
    if(res=="Enum")
      return "int";
    if(res=="Blob")
      return "byte[]";
    if(res=="List")
      return "List";
    if(res=="Event")
      return "EventClass";
    if(res=="Other")
      return "class";
    return res;
  }
  else
	  return cfType;
}

function fout(s){
  //公共函数：输出行
  curOut.add('    '+s);
}

  %>

}

