<%
/*
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.erupt.ezdemo';

var tb=curTable; //当前表
var ClsName=AutoCapProc(tb.name,'ClassNameSafe'); //类名（驼峰命名，首字母大写，如果与保留字冲突则加Ez前缀）
var tableName=tb.realTableName;
if(ClsName.indexOf('Ez')==0 && tb.name.toLowerCase().indexOf('ez')!=0){ //如果类名被加Ez前缀，则表名也要加
  tableName='ez_'+tableName;
}
var dispName=tb.UIDisplayName; //逻辑显示名

var fds=tb.metaFields; //所有字段列表

var sFieldEditorTypes=null;//预定义字段关系，不知为何放后面会报错

%>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 xyz.erupt.annotation.*;
import xyz.erupt.annotation.sub_erupt.*;
import xyz.erupt.annotation.sub_field.*;
import xyz.erupt.annotation.sub_field.sub_edit.*;
import xyz.erupt.upms.model.base.HyperModel;
import xyz.erupt.jpa.model.BaseModel;
import java.util.*;
import java.util.Date;
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;

<%
  //添加外键引用类，并判断主键是否引用了其它表
  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;
        //要在同一个模型才添加引用
        var cmtb=curModel.tables.itemByName(rtb.name, false);
        if(!cmtb)
          continue;
        if(!cmtb.isChecked)
          continue;
        if(fd.keyFieldType=='cfktId')
          if(!rfTbName)
            rfTbName=rtb.name;
        importTbs[rtb.name]=rtb.name;
      }
    }
  }

  var searchableCount=0; //计算有多少可搜索的字段
  for(var k=0; k<fds.count; k++) 
  { //字段循环开始
    var fd = fds.getItem(k); //取第k个字段
    if(!fd.isPhysicalField()) //判断字段是否物理字段
      continue;
      if(fd.queryable)
        searchableCount++;
      else if(fd.searchable)
        searchableCount++;
  }
  //如果没有配置可搜索的字段，默认前4个字段可搜索
  var autoSearchCount=0;
  if(searchableCount==0)
    autoSearchCount=4;

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

  
  //获取关联信息：引用了自己的所有子表
  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;
    if(!cmtb.isChecked)
      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;
        }
    }
  }

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

@Erupt(
    name = "${dispName}",<%
    var pkf=tb.getPrimaryKeyField();
    if(pkf && pkf.name.toLowerCase()!='id')
      fout('primaryKeyCol = "'+pkf.name + '",');
    if(tb.memo!='')
      fout('desc = "'+enline(tb.memo) + '",');
    %>
    power = @Power(importable = true, export = true)
)
@Table(name = "${tableName}")   //数据库表名
@Entity<% if(hasOneToOne){ %>
@Inheritance(strategy = InheritanceType.JOINED)<% } %>
public class ${ClsName}${extCls}{

<%    
  if(!tb.getPrimaryKeyField()){
    //没有主键的，手工加一个ID
    fout('//注意：本对象没有主键不符合要求，EZDML补了一个ID主键，避免运行出错');
    fout('@Id');
    fout('@GeneratedValue');
    fout('@EruptField()');
    fout('private long id;');
    fout('');
  }

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

    var fdn=AutoCapProc(fd.name,'FieldName');

    var tp=getFieldJavaType(fd); //数据类型
    if(fd.keyFieldType=='cfktId'){ //主键？
      //继承的子类，不输出ID
      if(extCls)
        if(fd.name.toLowerCase()=='id')
          continue;
      fout('@Id');
      if(tp=='Integer'){
        fout('@GeneratedValue(generator="generator")');
        fout('@GenericGenerator(name="generator", strategy="native")');
        tp='Long';
      } else {
        fout('@GeneratedValue(generator="sys_uuid")');
        fout('@GenericGenerator(name="sys_uuid", strategy="uuid")');
      }
    }
    
    var relateTb='';
    var relateFd='';
    if(fd.keyFieldType=='cfktRid'){ //外键？
      var cf=fd.getRelateTableField(); //外键引用的表字段是否存在
      if(cf){
        var rtb=fd.getRelateTableObj();
        //必须在同一个模型中，且已勾选，才输出
        var bSameModel=true;
        var cmtb=curModel.tables.itemByName(rtb.name, false);
        if(!cmtb)
          bSameModel=false;
        else if(!cmtb.isChecked)
          bSameModel=false;
        if (bSameModel){
          if(fd.indexType=='cfitUnique') //多对一或一对一
            fout('@OneToOne');
          else
            fout('@ManyToOne');
          relateTb=rtb.name;
          relateFd=rtb.getTitleFieldName();
          if(!relateFd)
            relateFd=rtb.metaFields.getItem(0).name;
          //输出关联字段
          fout('@JoinColumn(name = "'+AutoCapProc(fd.name,'FieldName')+'")');
        } else {
          fout('// 关联表没有同时勾选生成，只输出普通字段');
        }
      }
    }

    //输出字段长度、唯一、非空信息
    var colProps='';
    if(fd.dataType=='cfdtString')
      if(!fd.isLobField())
        if(fd.dataLength>0){
          if(colProps)
            colProps+=', ';
          colProps+='length = '+fd.dataLength;
        }
    if(fd.dataType=='cfdtFloat')
      if(fd.dataLength>0){
        if(colProps)
          colProps+=', ';
        colProps+='precision = '+fd.dataLength;
        if(fd.dataScale>0)
          colProps+=', scale = '+fd.dataScale;
      }
    if(!fd.nullable){
      if(colProps)
        colProps+=', ';
      colProps+='nullable = false';
    }
    if(fd.indexType=='cfitUnique'){
      if(colProps)
        colProps+=', ';
      colProps+='unique = true';
    }
    if(!relateFd) //排除外键
      if(colProps){
        fout('@Column('+colProps+')');
      }
    if(fd.isLobField())
    {
      fout('@Lob');
    }

    fout('@EruptField(');
    var hasV=false;
    var hasE=false;
    if(fd.canDisplay('grid')){ //列表中显示？
      fout2('views = @View(');
      foutV('title = "'+fd.getLabelText()+'"',true);
      if(fd.memo)
        foutV('desc = "'+enline(fd.memo)+'"');
      if(relateFd)
        foutV('column = "'+AutoCapProc(relateFd,'FieldName')+'"');
      var colTp=getFieldColType(fd);
      if(colTp)
        foutV('type = "'+colTp+'"');
      if(fd.colSortable)
        foutV('sortable = true');
      if(fd.exportable)
        foutV('export = true');
      var W = fd.colWidth; //获取字段宽度
      if(W <= 10)
        W = 120;
      foutV('width = "'+W+'"');
      fout2(')');
      hasV=true;
    }

    if(fd.canDisplay('sheet')){ //表单中显示？
      if(hasV)
        PrintVar(',');
      fout2('edit = @Edit(');
      foutV('title = "'+fd.getLabelText()+'"',true);
      if(fd.memo)
        foutV('desc = "'+enline(fd.memo)+'"');
      if(fd.isRequired())
        foutV('notNull = true');
      if(fd.editorReadOnly)
        foutV('readonly = true');
      if(fd.hint)
        foutV('placeHolder = "'+fd.hint+'"');
      if(relateFd){
        foutV('type = EditType.REFERENCE_TABLE');
        foutV('referenceTableType = @ReferenceTableType(label = "'+AutoCapProc(relateFd,'FieldName')+'")');
      } else{
        writeFieldEditor(fd);
      }
      //可查询搜索？
      if(fd.queryable)
        foutV('search = @Search');
      else if(fd.searchable)
        foutV('search = @Search');
      else if (autoSearchCount>0)
      {
        autoSearchCount--;
        foutV('search = @Search');
      }
      fout2(')');
      hasE=true;
    }
    if(hasE)
      fout(')');
    else if(hasV)
      fout(')')
    else
      PrintVar(')');
    if(relateFd){ //外键？
      fout('private '+AutoCapProc(relateTb,'ClassNameSafe')+' '+AutoCapProc(relateTb,'FieldName')+';');
    } else {
      fout('private '+tp+' '+fdn+';');
    }
    fout('');
  }
 

  //输出所有引用自己的子表
  for(var rtbName in refTbs){
    var rClsName=AutoCapProc(refTbs[rtbName],'FieldName');
    rClsName=removeFieldSubfixId(rClsName);

    var rTitle=rClsName; //子表名称
    var cmtb=curModel.tables.itemByName(rtbName, false);
    if(cmtb)
      rTitle=cmtb.UIDisplayName;

    var fdn=AutoCapProc(rtbName,'FieldName')+'List';
    var fd=tb.fieldOfChildTable(rtbName); //默认不输出子表的内容，除非在表里手工添加List字段
    var hasFd=false;
    if(fd){
      hasFd=true;
      fdn=AutoCapProc(fd.name,'FieldName');
    }

    if(!hasFd){ //默认注释掉，除非显式地定义了子对象列表
      fout('/*');
    }
    fout('@OneToMany(cascade=CascadeType.ALL)');
    fout('@JoinColumn(name = "'+refTbs[rtbName]+'")');
    fout('@EruptField(');
    fout2('edit = @Edit(title = "'+rTitle+'列表", type = EditType.TAB_TABLE_ADD)');
    fout(')');
    fout('private Set<'+AutoCapProc(rtbName,'ClassNameSafe')+'> '+fdn+';');
    if(!hasFd)
      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 "Integer";
    if(res=="Float")
      return "Float";
    if(res=="Bool")
      return "Boolean";
    if(res=="Enum")
      return "Integer";
    if(res=="Blob")
      return "String";
    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);
}         
function fout2(s){
  curOut.add('        '+s);
}          
function foutV(s,bFirst){
  if(!bFirst)
    PrintVar(',\n            '+s);
  else
    PrintVar('\n            '+s);
}
function enline(s){
  if(!s)
    return s;
  s = s.replace(/\r/g, '\\r');
  s = s.replace(/\n/g, '\\n');
  return s;
}
function getFieldColType(fd){
  //列表的列类型：暂时自动
  return '';
}

//以下是获取字段编辑器相关的了



function getFieldEditorType(fped){
  if(!fped)
    return '';
  //编辑器类型对应关系
  if(!sFieldEditorTypes)
    sFieldEditorTypes={
      'TextEdit': 'INPUT',
      'Memo': 'TEXTAREA',
      'RichText': 'HTML_EDITOR',
      'Password': 'INPUT',    
      'GUID': 'INPUT',
      'ButtonEdit': 'INPUT',
      'ComboBox': 'CHOICE',
      'ListSelect': 'CHOICE',
      'TagEdit': 'TAGS',
      'RadioBox': 'CHOICE',
      'ButtonGroup': 'TAGS',
      'CheckBox': 'CHECKBOX',
      'Switch': 'BOOLEAN',
      'SpinEdit': 'NUMBER',
      'NumberEdit': 'NUMBER',
      'CalcEdit': 'NUMBER',
      'TrackBar': 'SLIDER',
      'ScoreRate': 'SLIDER',
      'CurrencyEdit': 'NUMBER',
      'DateEdit': 'DATE',
      'DateRange': 'DATE',
      'TimeEdit': 'DATE',
      'DateTime': 'DATE',
      'WeekSelect': 'DATE',
      'MonthSelect': 'DATE',
      'QuarterSelect': 'DATE',
      'YearSelect': 'DATE',
      'ColorSelect': 'INPUT',
      'DataGrid': 'REFERENCE_TABLE',
      'KeyValueList': 'REFERENCE_TABLE',
      'FileNameEdit': 'INPUT',
      'ImageFile': 'ATTACHMENT',
      'UploadFile': 'ATTACHMENT',
      'LocationMap': 'MAP',
      'Button': 'TAGS',
      'HyperLink': 'INPUT',
      'Picture': 'ATTACHMENT',
      'BarCode': 'INPUT',   
      'QRCode': 'INPUT',
      'Chart': 'INPUT'};
  var edtpx=sFieldEditorTypes[fped];
  if(!edtpx)
    return '';
  return edtpx;
}

function getDropdownItems(fd){
  //为字段生成下拉项列表
  var res=[];
  var ddstr=fd.dropDownItems; //这个返回的是回车换行分隔的字符串
  if(!ddstr)
    ddstr=fd.getDemoItemList(false);
  if(!ddstr)
    return res;

  ddstr=ddstr.replace(/\r\n/g, "\n"); //替换掉\r
  var ddss=ddstr.split("\n"); //按行分隔
  for(var idx in ddss){ //遍历每一项
    var s=ddss[idx];
    if(!s)
      continue;
    var po=s.indexOf("="); //如果有等号，等号左边是值，右较是显示文本
    var t,v;
    var hasVal=false;
    if(po<0){
      t=s;
      v=s;
    } else {
      t=s.substring(po+1);
      v=s.substring(0,po);
      hasVal=false;
    }
    var bExists=false;
    for(var idx in res){
      if(res[idx].value==v){
        bExists=true;
        break;
      }
    }
    if(!bExists)
      res.push({text: t, value: v, hasVal: hasVal});
  }
  return res;
}

function getDropdownItemsVL(fd){
  //为字段生成下拉项列表
  //{@VL(value = "xxx", label = "xxx"), @VL(value = "yyy", label = "yyy")}
  var opts=getDropdownItems(fd);
  var res='';
  var sp='                              ';
  for(var idx in opts){
    var opt=opts[idx];
    if(res)
      res=res+',\n';
    var val=opt.value;
    if(!opt.hasVal)
      if(fd.dataType=='cfdtInteger')
        val=idx;
    res=res+sp+'@VL(value = "'+val+'", label = "'+opt.text+'")';
  }
  return '{\n'+res+'\n                          }';
}

function getDropdownItemsTag(fd){
  //为字段生成下拉项列表
  //{"普通会员", "铜牌会员", "银牌会员", "黄金会员", "白金会员"  }
  var opts=getDropdownItems(fd);
  var res='';
  var sp='                              ';
  for(var idx in opts){
    var opt=opts[idx];
    if(res)
      res=res+',\n';
    res=res+sp+'"'+opt.text+'"';
  }
  return '{\n'+res+'\n                          }';
}

function getDropdownItemsBool(fd){
  //为字段生成下拉项列表
  //{'true':'男', 'false':'女'}
  var opts=getDropdownItems(fd);
  var res={};
  var opt1=opts[0];
  var opt2=opts[1];
  if(opt1.hasVal){
    if(opt1.value){
      res['true']=opt1.text;
      res['false']=opt2.text;
    } else{
      res['true']=opt2.text;
      res['false']=opt1.text;
    }
    return res;
  }
  
  res['true']=opt2.text;
  res['false']=opt1.text;
  return res;
}

function writeFieldEditor(fd){
  //输出字段编辑器信息
  if(!fd)
    return;
  
  var oTp=fd.possibleEditorType(); //获取字段编辑器类型
  var edTp=getFieldEditorType(oTp); //转成erupt对应的类型

  if(!edTp){ //转不了就用默认的
    if(fd.dropDownMode=='cfddAutoComplete'){
         foutV('type = EditType.AUTO_COMPLETE');
         return;
    }
    return;
  }


  if (oTp=='Password')
  {
     foutV('type = EditType.'+edTp);
     foutV('inputType = @InputType(type = "password")');
     return;
  }
  if (oTp=='RichText')
  {
     foutV('type = EditType.'+edTp);
     foutV('htmlEditorType = @HtmlEditorType(HtmlEditorType.Type.UEDITOR)');
     return;
  }
  if (edTp=='CHOICE')
  {
     foutV('type = EditType.'+edTp);
     if(fd.dropDownSQL){
       var sql=fd.dropDownSQL.replace(/\r/g,' ');
       sql=sql.replace(/\n/g,' ');
       var s='choiceType = @ChoiceType(fetchHandler = SqlChoiceFetchHandler.class,\n'+
'                              fetchHandlerParams = "'+sql+'"\n'+
'                          )';
       foutV(s);
     } else {
       var dds=getDropdownItemsVL(fd);
       foutV('choiceType = @ChoiceType(vl = '+dds+')');
     }
     return;
  }
  if (edTp=='TAGS')
  {
     foutV('type = EditType.'+edTp);
     if(fd.dropDownSQL){
       var sql=fd.dropDownSQL.replace(/\r/g,' ');
       sql=sql.replace(/\n/g,' ');
       var s='tagsType = @TagsType(fetchHandler= SqlTagFetchHandler.class,\n'+
'                              fetchHandlerParams = "'+sql+'"\n'+
'                          )';
       foutV(s);
     } else {
       var dds=getDropdownItemsTag(fd);
       foutV('tagsType = @TagsType(tags = '+dds+')');
     }
     return;
  }
  if(oTp=='CheckBox'){
     if(fd.dataType=='cfdtBool' || fd.dataType=='cfdtInteger'){
       foutV('type = EditType.BOOLEAN');
       var ddst=getDropdownItems(fd);
       if(ddst){
         var dds=getDropdownItemsBool(fd);
         if(dds.length>=2)
           foutV('boolType = @BoolType(trueText = "'+dds['true']+'", falseText = "'+dds['false']+'")');
       }
     } else if(fd.dropDownSQL){
       foutV('type = EditType.TAGS');
       var sql=fd.dropDownSQL.replace(/\r/g,' ');
       sql=sql.replace(/\n/g,' ');
       var s='tagsType = @TagsType(fetchHandler= SqlTagFetchHandler.class,\n'+
'                              fetchHandlerParams = "'+sql+'"\n'+
'                          )';
       foutV(s);
     } else if(getDropdownItems(fd)){
       var dds=getDropdownItemsTag(fd);
       foutV('type = EditType.TAGS');
       foutV('tagsType = @TagsType(tags = '+dds+')');
     } else {
       foutV('type = EditType.BOOLEAN');
     }
     return;
  }

  if(oTp=='DateEdit'){
     foutV('type = EditType.DATE');
     foutV('dateType = @DateType(type = DateType.Type.DATE)');
     return;
  }
  
  if(oTp=='DateTime'){
     foutV('type = EditType.DATE');
     foutV('dateType = @DateType(type = DateType.Type.DATE_TIME)');
     return;
  }
  
  if(oTp=='TimeEdit'){
     foutV('type = EditType.DATE');
     foutV('dateType = @DateType(type = DateType.Type.TIME)');
     return;
  }

  if(oTp=='WeekSelect'){
     foutV('type = EditType.DATE');
     foutV('dateType = @DateType(type = DateType.Type.WEEK)');
     return;
  }

  if(oTp=='MonthSelect' || oTp=='QuarterSelect'){
     foutV('type = EditType.DATE');
     foutV('dateType = @DateType(type = DateType.Type.MONTH)');
     return;
  }

  if(oTp=='YearSelect'){
     foutV('type = EditType.DATE');
     foutV('dateType = @DateType(type = DateType.Type.YEAR)');
     return;
  }

  if(oTp=='DateRange'){
      //没有合适的?
     foutV('type = EditType.DATE');
     foutV('dateType = @DateType(type = DateType.Type.DATE)');
     return;
  }

  if(oTp=='ColorSelect'){
       foutV('inputType = @InputType(type = "color")');
       return;
  }
  if(oTp=='ImageFile'){
       foutV('type = EditType.ATTACHMENT');
       foutV('attachmentType = @AttachmentType(type = AttachmentType.Type.IMAGE)');
       return;
  }
  if( oTp=='Picture'){
       foutV('type = EditType.ATTACHMENT');
       foutV('attachmentType = @AttachmentType(type = AttachmentType.Type.IMAGE, maxLimit = 1)');
       return;
  }
  if(oTp=='UploadFile'){
       foutV('type = EditType.ATTACHMENT');
       return;
  }
  

  if(fd.dropDownMode=='cfddAutoComplete'){
       foutV('type = EditType.AUTO_COMPLETE');
       return;
  }
}


  %>

}

