001 package railo.runtime.orm.hibernate; 002 003 004 import java.util.ArrayList; 005 import java.util.HashMap; 006 import java.util.Iterator; 007 import java.util.Map; 008 import java.util.Map.Entry; 009 010 import org.w3c.dom.Document; 011 import org.w3c.dom.Element; 012 import org.w3c.dom.NodeList; 013 014 import railo.commons.lang.StringUtil; 015 import railo.runtime.Component; 016 import railo.runtime.ComponentPro; 017 import railo.runtime.PageContext; 018 import railo.runtime.component.Property; 019 import railo.runtime.db.DatasourceConnection; 020 import railo.runtime.exp.PageException; 021 import railo.runtime.op.Caster; 022 import railo.runtime.op.Decision; 023 import railo.runtime.orm.ORMConfiguration; 024 import railo.runtime.orm.ORMEngine; 025 import railo.runtime.orm.ORMException; 026 import railo.runtime.text.xml.XMLUtil; 027 import railo.runtime.type.Collection; 028 import railo.runtime.type.Collection.Key; 029 import railo.runtime.type.KeyImpl; 030 import railo.runtime.type.List; 031 import railo.runtime.type.Struct; 032 import railo.runtime.type.StructImpl; 033 import railo.runtime.type.dt.DateTimeImpl; 034 import railo.runtime.type.util.ArrayUtil; 035 import railo.runtime.type.util.ComponentUtil; 036 037 public class HBMCreator { 038 039 040 private static final Collection.Key PROPERTY = KeyImpl.intern("property"); 041 private static final Collection.Key FIELD_TYPE = KeyImpl.intern("fieldType"); 042 private static final Collection.Key LINK_TABLE = KeyImpl.intern("linktable"); 043 private static final Collection.Key CFC = KeyImpl.intern("cfc"); 044 private static final Collection.Key GENERATOR = KeyImpl.intern("generator"); 045 private static final Collection.Key PARAMS = KeyImpl.intern("params"); 046 private static final Collection.Key SEQUENCE = KeyImpl.intern("sequence"); 047 private static final Collection.Key UNIQUE_KEY_NAME = KeyImpl.intern("uniqueKeyName"); 048 private static final Collection.Key GENERATED = KeyImpl.intern("generated"); 049 050 public static void createXMLMapping(PageContext pc,DatasourceConnection dc, Component cfc,ORMConfiguration ormConf,Element hibernateMapping,HibernateORMEngine engine) throws PageException { 051 052 // MUST Support for embeded objects 053 ComponentPro cfci = ComponentUtil.toComponentPro(cfc); 054 Struct meta = cfci.getMetaData(pc); 055 056 String extend = cfc.getExtends(); 057 boolean isClass=StringUtil.isEmpty(extend); 058 059 Property[] _props=getProperties(pc,engine,cfci,dc,ormConf,meta,isClass); 060 061 062 063 Map<String, PropertyCollection> joins=new HashMap<String, PropertyCollection>(); 064 PropertyCollection propColl = splitJoins(engine,cfc,joins, _props); 065 066 067 068 // create class element and attach 069 Document doc = XMLUtil.getDocument(hibernateMapping); 070 071 StringBuilder comment=new StringBuilder(); 072 comment.append("\nsource:").append(cfci.getPageSource().getDisplayPath()); 073 comment.append("\ncompilation-time:").append(new DateTimeImpl(ComponentUtil.getCompileTime(pc,cfci.getPageSource()),false)).append("\n"); 074 075 hibernateMapping.appendChild(doc.createComment(comment.toString())); 076 077 //print.e(cfc.getAbsName()+";"+isClass+" -> "+cfci.getBaseAbsName()+":"+cfci.isBasePeristent()); 078 if(!isClass && !cfci.isBasePeristent()) { 079 isClass=true; 080 } 081 082 083 Element join=null; 084 boolean doTable=true; 085 086 Element clazz; 087 if(isClass) { 088 clazz = doc.createElement("class"); 089 hibernateMapping.appendChild(clazz); 090 } 091 // extended CFC 092 else{ 093 String ext = List.last(extend,'.').trim(); 094 try { 095 Component base = engine.getEntityByCFCName(ext, false); 096 ext = HibernateCaster.getEntityName(base); 097 } 098 catch(Throwable t){} 099 100 101 String discriminatorValue = toString(engine,cfc,null,meta,"discriminatorValue"); 102 if(!StringUtil.isEmpty(discriminatorValue,true)) { 103 doTable=false; 104 clazz = doc.createElement("subclass"); 105 hibernateMapping.appendChild(clazz); 106 //addClassAttributes(classNode); 107 clazz.setAttribute("extends", ext); 108 clazz.setAttribute("discriminator-value", discriminatorValue); 109 110 String joincolumn = toString(engine,cfc,null,meta,"joincolumn",false); 111 if(!StringUtil.isEmpty(joincolumn)){ 112 join = doc.createElement("join"); 113 clazz.appendChild(join); 114 doTable=true; 115 Element key = doc.createElement("key"); 116 join.appendChild(key); 117 key.setAttribute("column", formatColumn(engine,joincolumn)); 118 } 119 120 } 121 else { 122 clazz = doc.createElement("joined-subclass"); 123 hibernateMapping.appendChild(clazz); 124 clazz.setAttribute("extends",ext); 125 Element key = doc.createElement("key"); 126 clazz.appendChild(key); 127 key.setAttribute("column", formatColumn(engine,toString(engine,cfc,null,meta,"joincolumn",true))); 128 } 129 130 } 131 132 //createXMLMappingTuplizer(clazz,pc); 133 134 addGeneralClassAttributes(pc,ormConf,engine,cfc,meta,clazz); 135 String tableName=getTableName(engine,pc,meta,cfc); 136 137 if(join!=null) clazz=join; 138 if(doTable)addGeneralTableAttributes(pc,ormConf,engine,cfc,meta,clazz); 139 140 141 142 143 Struct columnsInfo=null; 144 if(ormConf.useDBForMapping()){ 145 columnsInfo = engine.getTableInfo(dc,getTableName(engine,pc, meta, cfci),engine); 146 } 147 148 if(isClass)setCacheStrategy(engine,cfc,null,doc, meta, clazz); 149 150 // id 151 if(isClass) addId(cfc,doc,clazz,pc,meta,propColl,columnsInfo,tableName,engine); 152 153 // discriminator 154 if(isClass) addDiscriminator(engine,cfc,doc,clazz,pc,meta); 155 156 // version 157 if(isClass)addVersion(cfc,clazz,pc, propColl,columnsInfo,tableName,engine); 158 159 // property 160 addProperty(cfc,clazz,pc, propColl,columnsInfo,tableName,engine); 161 162 // relations 163 addRelation(cfc,clazz,pc, propColl,columnsInfo,tableName,engine,ormConf,dc); 164 165 // collection 166 addCollection(cfc,clazz,pc, propColl,columnsInfo,tableName,engine,ormConf); 167 168 // join 169 addJoin(cfc,clazz,pc, joins,columnsInfo,tableName,engine,ormConf,dc); 170 171 172 } 173 174 private static Property[] getProperties(PageContext pc, HibernateORMEngine engine, ComponentPro cfci, DatasourceConnection dc, ORMConfiguration ormConf, Struct meta, boolean isClass) throws ORMException, PageException { 175 Property[] _props = cfci.getProperties(true); 176 if(isClass && _props.length==0 && ormConf.useDBForMapping()){ 177 if(meta==null)meta = cfci.getMetaData(pc); 178 _props=HibernateUtil.createPropertiesFromTable(dc,getTableName(engine,pc, meta, cfci)); 179 } 180 return _props; 181 } 182 183 184 185 186 187 188 189 190 191 192 193 194 private static void addId(Component cfc,Document doc, Element clazz, PageContext pc, Struct meta, PropertyCollection propColl, Struct columnsInfo, String tableName, HibernateORMEngine engine) throws PageException { 195 Property[] _ids = getIds(engine,cfc,propColl); 196 197 //Property[] _ids = ids.toArray(new Property[ids.size()]); 198 199 if(_ids.length==1) 200 createXMLMappingId(cfc,clazz,pc, _ids[0],columnsInfo,tableName,engine); 201 else if(_ids.length>1) 202 createXMLMappingCompositeId(cfc,clazz,pc, _ids,columnsInfo,tableName,engine); 203 else 204 throw new HibernateException(engine,cfc,"missing id property for entity ["+HibernateCaster.getEntityName(cfc)+"]"); 205 } 206 207 208 public static PropertyCollection splitJoins(HibernateORMEngine engine,Component cfc,Map<String, PropertyCollection> joins,Property[] props) { 209 Struct sct=new StructImpl(); 210 ArrayList<Property> others = new ArrayList<Property>(); 211 java.util.List<Property> list; 212 String table; 213 Property prop; 214 String fieldType; 215 boolean isJoin; 216 for(int i=0;i<props.length;i++){ 217 prop=props[i]; 218 table=getTable(engine,cfc,prop); 219 // joins 220 if(!StringUtil.isEmpty(table,true)){ 221 isJoin=true; 222 // wrong field type 223 try { 224 fieldType = toString(engine, cfc, prop, sct, FIELD_TYPE,false); 225 226 if("collection".equalsIgnoreCase(fieldType)) isJoin=false; 227 else if("primary".equals(fieldType)) isJoin=false; 228 else if("version".equals(fieldType)) isJoin=false; 229 else if("timestamp".equals(fieldType)) isJoin=false; 230 } 231 catch (ORMException e) {} 232 233 // missing column 234 String columns=null; 235 try { 236 if(isRelated(props[i])){ 237 columns=toString(engine,cfc,props[i], prop.getDynamicAttributes(), "fkcolumn"); 238 } 239 else { 240 columns=toString(engine,cfc,props[i], prop.getDynamicAttributes(), "joincolumn"); 241 } 242 } 243 catch(ORMException e){} 244 if(StringUtil.isEmpty(columns)) isJoin=false; 245 246 if(isJoin){ 247 table=table.trim(); 248 list = (java.util.List<Property>) sct.get(table,null); 249 if(list==null){ 250 list=new ArrayList<Property>(); 251 sct.setEL(KeyImpl.init(table), list); 252 } 253 list.add(prop); 254 continue; 255 } 256 } 257 others.add(prop); 258 } 259 260 // fill to joins 261 Key[] keys = sct.keys(); 262 Key key; 263 for(int i=0;i<keys.length;i++){ 264 key=keys[i]; 265 list=(java.util.List<Property>) sct.get(key,null); 266 joins.put(key.getString(), new PropertyCollection(key.getString(),list)); 267 } 268 269 270 271 return new PropertyCollection(null,others); 272 } 273 274 275 276 277 278 public static Property[] getIds(HibernateORMEngine engine,Component cfc,PropertyCollection pc) { 279 return getIds(engine,cfc,pc.getProperties(), pc.getTableName(),false); 280 } 281 282 public static Property[] getIds(HibernateORMEngine engine,Component cfc,Property[] props,String tableName, boolean ignoreTableName) { 283 ArrayList<Property> ids=new ArrayList<Property>(); 284 for(int y=0;y<props.length;y++){ 285 if(!ignoreTableName && !hasTable(engine,cfc,props[y], tableName)) continue; 286 287 288 String fieldType = Caster.toString(props[y].getDynamicAttributes().get(FIELD_TYPE,null),null); 289 if("id".equalsIgnoreCase(fieldType) || List.listFindNoCaseIgnoreEmpty(fieldType,"id",',')!=-1) 290 ids.add(props[y]); 291 } 292 293 // no id field defined 294 if(ids.size()==0) { 295 String fieldType; 296 for(int y=0;y<props.length;y++){ 297 if(!ignoreTableName && !hasTable(engine,cfc,props[y], tableName)) continue; 298 fieldType = Caster.toString(props[y].getDynamicAttributes().get(FIELD_TYPE,null),null); 299 if(StringUtil.isEmpty(fieldType,true) && props[y].getName().equalsIgnoreCase("id")){ 300 ids.add(props[y]); 301 props[y].getDynamicAttributes().setEL(FIELD_TYPE, "id"); 302 } 303 } 304 } 305 306 // still no id field defined 307 if(ids.size()==0 && props.length>0) { 308 String owner = props[0].getOwnerName(); 309 if(!StringUtil.isEmpty(owner)) owner=List.last(owner, '.').trim(); 310 311 String fieldType; 312 if(!StringUtil.isEmpty(owner)){ 313 String id=owner+"id"; 314 for(int y=0;y<props.length;y++){ 315 if(!ignoreTableName && !hasTable(engine,cfc,props[y], tableName)) continue; 316 fieldType = Caster.toString(props[y].getDynamicAttributes().get(FIELD_TYPE,null),null); 317 if(StringUtil.isEmpty(fieldType,true) && props[y].getName().equalsIgnoreCase(id)){ 318 ids.add(props[y]); 319 props[y].getDynamicAttributes().setEL(FIELD_TYPE, "id"); 320 } 321 } 322 } 323 } 324 return ids.toArray(new Property[ids.size()]); 325 } 326 327 328 329 330 331 332 private static void addVersion(Component cfc,Element clazz, PageContext pc,PropertyCollection propColl, Struct columnsInfo, String tableName,HibernateORMEngine engine) throws PageException { 333 Property[] props = propColl.getProperties(); 334 for(int y=0;y<props.length;y++){ 335 String fieldType = Caster.toString(props[y].getDynamicAttributes().get(FIELD_TYPE,null),null); 336 if("version".equalsIgnoreCase(fieldType)) 337 createXMLMappingVersion(engine,clazz,pc, cfc,props[y]); 338 else if("timestamp".equalsIgnoreCase(fieldType)) 339 createXMLMappingTimestamp(engine,clazz,pc,cfc, props[y]); 340 } 341 } 342 343 344 345 private static void addCollection(Component cfc,Element clazz, PageContext pc,PropertyCollection propColl, Struct columnsInfo, String tableName,HibernateORMEngine engine, ORMConfiguration ormConf) throws PageException { 346 Property[] props = propColl.getProperties(); 347 for(int y=0;y<props.length;y++){ 348 String fieldType = Caster.toString(props[y].getDynamicAttributes().get(FIELD_TYPE,"column"),"column"); 349 if("collection".equalsIgnoreCase(fieldType)) 350 createXMLMappingCollection(clazz,pc, cfc,props[y],ormConf,engine); 351 } 352 } 353 354 355 private static void addJoin(Component cfc,Element clazz, PageContext pc,Map<String, PropertyCollection> joins, Struct columnsInfo, String tableName,HibernateORMEngine engine, ORMConfiguration ormConf, DatasourceConnection dc) throws PageException { 356 357 Iterator<Entry<String, PropertyCollection>> it = joins.entrySet().iterator(); 358 Entry<String, PropertyCollection> entry; 359 while(it.hasNext()){ 360 entry = it.next(); 361 addJoin(cfc,engine,pc,columnsInfo,ormConf,clazz,entry.getValue(),dc); 362 } 363 364 365 366 } 367 368 private static void addJoin(Component cfc,HibernateORMEngine engine,PageContext pc,Struct columnsInfo, ORMConfiguration ormConf, Element clazz, PropertyCollection coll, DatasourceConnection dc) throws PageException { 369 String table = coll.getTableName(); 370 Property[] properties = coll.getProperties(); 371 if(properties.length==0) return; 372 373 Document doc = XMLUtil.getDocument(clazz); 374 375 Element join = doc.createElement("join"); 376 clazz.appendChild(join); 377 378 join.setAttribute("table", escape(engine.convertTableName(coll.getTableName()))); 379 //addTableInfo(joinNode, table, schema, catalog); 380 381 Property first = properties[0]; 382 String schema = null, catalog=null, mappedBy=null, columns=null; 383 if(isRelated(first)){ 384 catalog=toString(engine,cfc,first, first.getDynamicAttributes(), "linkcatalog"); 385 schema=toString(engine,cfc,first, first.getDynamicAttributes(), "linkschema"); 386 columns=toString(engine,cfc,first, first.getDynamicAttributes(), "fkcolumn"); 387 388 } 389 else { 390 catalog=toString(engine,cfc,first, first.getDynamicAttributes(), "catalog"); 391 schema=toString(engine,cfc,first, first.getDynamicAttributes(), "schema"); 392 mappedBy=toString(engine,cfc,first, first.getDynamicAttributes(), "mappedby"); 393 columns=toString(engine,cfc,first, first.getDynamicAttributes(), "joincolumn"); 394 } 395 396 if(!StringUtil.isEmpty(catalog)) join.setAttribute("catalog", catalog); 397 if(!StringUtil.isEmpty(schema)) join.setAttribute("schema", schema); 398 399 Element key = doc.createElement("key"); 400 join.appendChild(key); 401 if(!StringUtil.isEmpty(mappedBy)) key.setAttribute("property-ref", mappedBy); 402 setColumn(engine,doc, key, columns); 403 404 addProperty(cfc,join,pc, coll,columnsInfo,table,engine); 405 int count=addRelation(cfc,join,pc, coll,columnsInfo,table,engine, ormConf,dc); 406 407 if(count>0) join.setAttribute("inverse", "true"); 408 409 410 } 411 412 413 414 415 416 417 418 419 420 421 422 private static int addRelation(Component cfc,Element clazz, PageContext pc,PropertyCollection propColl, Struct columnsInfo, String tableName,HibernateORMEngine engine, ORMConfiguration ormConf, DatasourceConnection dc) throws PageException { 423 Property[] props = propColl.getProperties(); 424 int count=0; 425 for(int y=0;y<props.length;y++){ 426 String fieldType = Caster.toString(props[y].getDynamicAttributes().get(FIELD_TYPE,"column"),"column"); 427 if("one-to-one".equalsIgnoreCase(fieldType)){ 428 createXMLMappingOneToOne(clazz,pc, cfc,props[y],engine); 429 count++; 430 } 431 else if("many-to-one".equalsIgnoreCase(fieldType)){ 432 createXMLMappingManyToOne(clazz,pc, cfc,props[y],engine,propColl); 433 count++; 434 } 435 else if("one-to-many".equalsIgnoreCase(fieldType)){ 436 createXMLMappingOneToMany(cfc,engine,propColl,ormConf,clazz,pc, props[y]); 437 count++; 438 } 439 else if("many-to-many".equalsIgnoreCase(fieldType)){ 440 createXMLMappingManyToMany(cfc,engine,propColl,clazz,pc, props[y],ormConf,dc); 441 count++; 442 } 443 } 444 return count; 445 } 446 447 public static boolean isRelated(Property prop) { 448 String fieldType = Caster.toString(prop.getDynamicAttributes().get(FIELD_TYPE,"column"),"column"); 449 if(StringUtil.isEmpty(fieldType,true)) return false; 450 fieldType=fieldType.toLowerCase().trim(); 451 452 if("one-to-one".equals(fieldType)) return true; 453 if("many-to-one".equals(fieldType)) return true; 454 if("one-to-many".equals(fieldType)) return true; 455 if("many-to-many".equals(fieldType)) return true; 456 return false; 457 } 458 459 460 461 private static void addProperty(Component cfc,Element clazz, PageContext pc, PropertyCollection propColl, Struct columnsInfo, String tableName, HibernateORMEngine engine) throws ORMException { 462 Property[] props = propColl.getProperties(); 463 for(int y=0;y<props.length;y++){ 464 String fieldType = Caster.toString(props[y].getDynamicAttributes().get(FIELD_TYPE,"column"),"column"); 465 if("column".equalsIgnoreCase(fieldType)) 466 createXMLMappingProperty(clazz,pc,cfc, props[y],columnsInfo,tableName,engine); 467 } 468 } 469 470 471 472 private static void addDiscriminator(HibernateORMEngine engine,Component cfc,Document doc,Element clazz, PageContext pc,Struct meta) throws ORMException { 473 474 String str = toString(engine,cfc,null,meta,"discriminatorColumn"); 475 if(!StringUtil.isEmpty(str,true)){ 476 Element disc = doc.createElement("discriminator"); 477 clazz.appendChild(disc); 478 disc.setAttribute("column",formatColumn(engine,str)); 479 } 480 481 482 483 484 } 485 486 487 488 private static void addGeneralClassAttributes(PageContext pc, ORMConfiguration ormConf, HibernateORMEngine engine, Component cfc, Struct meta, Element clazz) throws PageException { 489 490 // name 491 clazz.setAttribute("node", HibernateCaster.toComponentName(cfc)); 492 493 // entity-name 494 String str=toString(engine,cfc,null,meta,"entityname"); 495 if(StringUtil.isEmpty(str,true)) str=HibernateCaster.getEntityName(cfc); 496 clazz.setAttribute("entity-name",str); 497 498 499 // batch-size 500 Integer i = toInteger(engine,cfc,meta,"batchsize"); 501 if(i!=null && i.intValue()>0)clazz.setAttribute("batch-size",Caster.toString(i)); 502 503 // dynamic-insert 504 Boolean b = toBoolean(engine,cfc,meta,"dynamicinsert"); 505 if(b!=null && b.booleanValue())clazz.setAttribute("dynamic-insert","true"); 506 507 // dynamic-update 508 b=toBoolean(engine,cfc,meta,"dynamicupdate"); 509 if(b!=null && b.booleanValue())clazz.setAttribute("dynamic-update","true"); 510 511 // lazy (dtd defintion:<!ATTLIST class lazy (true|false) #IMPLIED>) 512 b=toBoolean(engine,cfc,meta,"lazy"); 513 if(b==null) b=Boolean.TRUE; 514 clazz.setAttribute("lazy",Caster.toString(b.booleanValue())); 515 516 // select-before-update 517 b=toBoolean(engine,cfc,meta,"selectbeforeupdate"); 518 if(b!=null && b.booleanValue())clazz.setAttribute("select-before-update","true"); 519 520 // optimistic-lock 521 str=toString(engine,cfc,null,meta,"optimisticLock"); 522 if(!StringUtil.isEmpty(str,true)) { 523 str=str.trim().toLowerCase(); 524 if("all".equals(str) || "dirty".equals(str) || "none".equals(str) || "version".equals(str)) 525 clazz.setAttribute("optimistic-lock",str); 526 else 527 throw new HibernateException(engine,cfc,"invalid value ["+str+"] for attribute [optimisticlock] of tag [component], valid values are [all,dirty,none,version]"); 528 } 529 530 // read-only 531 b=toBoolean(engine,cfc,meta,"readOnly"); 532 if(b!=null && b.booleanValue()) clazz.setAttribute("mutable", "false"); 533 534 // rowid 535 str=toString(engine,cfc,null,meta,"rowid"); 536 if(!StringUtil.isEmpty(str,true)) clazz.setAttribute("rowid",str); 537 538 // where 539 str=toString(engine,cfc,null,meta,"where"); 540 if(!StringUtil.isEmpty(str,true)) clazz.setAttribute("where", str); 541 542 543 } 544 private static void addGeneralTableAttributes(PageContext pc, ORMConfiguration ormConf, HibernateORMEngine engine, Component cfc, Struct meta, Element clazz) throws PageException { 545 // table 546 clazz.setAttribute("table",escape(getTableName(engine,pc,meta,cfc))); 547 548 // catalog 549 String str = toString(engine,cfc,null,meta,"catalog"); 550 if(str==null)// empty string is allowed as input 551 str=ormConf.getCatalog(); 552 if(!StringUtil.isEmpty(str,true)) clazz.setAttribute("catalog", str); 553 554 // schema 555 str=toString(engine,cfc,null,meta,"schema"); 556 if(str==null)// empty string is allowed as input 557 str=ormConf.getSchema(); 558 if(!StringUtil.isEmpty(str,true)) clazz.setAttribute( "schema", str); 559 560 } 561 private static String escape(String str) { 562 if(HibernateUtil.isKeyword(str)) return "`"+str+"`"; 563 return str; 564 } 565 566 567 568 569 570 571 private static String getTableName(HibernateORMEngine engine,PageContext pc, Struct meta, Component cfc) throws ORMException { 572 String tableName=toString(engine,cfc,null,meta,"table"); 573 if(StringUtil.isEmpty(tableName,true)) 574 tableName=HibernateCaster.getEntityName(cfc); 575 return engine.convertTableName(tableName); 576 } 577 578 private static String getTable(HibernateORMEngine engine,Component cfc,Property prop) { 579 try { 580 return engine.convertTableName(toString(engine,cfc,prop, prop.getDynamicAttributes(), "table")); 581 } catch (ORMException e) { 582 return null; 583 } 584 } 585 586 private static boolean hasTable(HibernateORMEngine engine,Component cfc,Property prop,String tableName) { 587 String t = getTable(engine,cfc,prop); 588 boolean left=StringUtil.isEmpty(t,true); 589 boolean right=StringUtil.isEmpty(tableName,true); 590 if(left && right) return true; 591 if(left || right) return false; 592 return tableName.trim().equalsIgnoreCase(t.trim()); 593 } 594 595 596 597 598 599 600 private static void createXMLMappingCompositeId(Component cfc,Element clazz, PageContext pc,Property[] props,Struct columnsInfo,String tableName,HibernateORMEngine engine) throws PageException { 601 Struct meta; 602 603 Document doc = XMLUtil.getDocument(clazz); 604 Element cid = doc.createElement("composite-id"); 605 clazz.appendChild(cid); 606 607 //cid.setAttribute("mapped","true"); 608 609 610 Property prop; 611 // ids 612 for(int y=0;y<props.length;y++){ 613 prop=props[y]; 614 meta = prop.getDynamicAttributes(); 615 Element key = doc.createElement("key-property"); 616 cid.appendChild(key); 617 618 // name 619 key.setAttribute("name",prop.getName()); 620 621 // column 622 Element column = doc.createElement("column"); 623 key.appendChild(column); 624 625 String str = toString(engine,cfc,prop,meta,"column"); 626 if(StringUtil.isEmpty(str,true)) str=prop.getName(); 627 column.setAttribute("name",formatColumn(engine,str)); 628 ColumnInfo info=getColumnInfo(columnsInfo,tableName,str,engine,null); 629 630 str = toString(engine,cfc,prop,meta,"sqltype"); 631 if(!StringUtil.isEmpty(str,true)) column.setAttribute("sql-type",str); 632 str = toString(engine,cfc,prop,meta,"length"); 633 if(!StringUtil.isEmpty(str,true)) column.setAttribute("length",str); 634 635 /*if(info!=null){ 636 column.setAttribute("sql-type",info.getTypeName()); 637 column.setAttribute("length",Caster.toString(info.getSize())); 638 }*/ 639 640 // type 641 //str=getType(info,prop,meta,"long"); //MUSTMUST 642 //key.setAttribute("type", str); 643 644 String generator=toString(engine,cfc,prop,meta,"generator"); 645 String type = getType(engine,info,cfc,prop,meta,getDefaultTypeForGenerator(generator,"string")); 646 if(!StringUtil.isEmpty(type))key.setAttribute("type", type); 647 648 649 650 651 } 652 653 // many-to-one 654 String fieldType; 655 for(int y=0;y<props.length;y++){ 656 prop=props[y]; 657 meta = prop.getDynamicAttributes(); 658 fieldType = toString(engine,cfc,prop,meta,"fieldType"); 659 if(List.listFindNoCaseIgnoreEmpty(fieldType,"many-to-one",',')==-1)continue; 660 661 Element key = doc.createElement("key-many-to-one"); 662 cid.appendChild(key); 663 664 // name 665 key.setAttribute("name",prop.getName()); 666 667 // entity-name 668 setForeignEntityName(pc, engine,cfc,prop, meta, key,false); 669 670 // fkcolum 671 String str=toString(engine,cfc,prop,meta,"fkcolumn"); 672 setColumn(engine,doc, key, str); 673 674 // lazy 675 setLazy(engine,cfc,prop,meta,key); 676 } 677 } 678 679 680 private static void createXMLMappingId(Component cfc,Element clazz, PageContext pc,Property prop,Struct columnsInfo,String tableName,HibernateORMEngine engine) throws PageException { 681 Struct meta = prop.getDynamicAttributes(); 682 String str; 683 684 Document doc = XMLUtil.getDocument(clazz); 685 Element id = doc.createElement("id"); 686 clazz.appendChild(id); 687 688 // access 689 str=toString(engine,cfc,prop,meta,"access"); 690 if(!StringUtil.isEmpty(str,true))id.setAttribute("access", str); 691 692 // name 693 id.setAttribute("name",prop.getName()); 694 695 // column 696 Element column = doc.createElement("column"); 697 id.appendChild(column); 698 699 str=toString(engine,cfc,prop,meta,"column"); 700 if(StringUtil.isEmpty(str,true)) str=prop.getName(); 701 column.setAttribute("name",formatColumn(engine,str)); 702 ColumnInfo info=getColumnInfo(columnsInfo,tableName,str,engine,null); 703 StringBuilder foreignCFC=new StringBuilder(); 704 String generator=createXMLMappingGenerator(engine,id,pc,cfc,prop,foreignCFC); 705 706 str = toString(engine,cfc,prop,meta,"length"); 707 if(!StringUtil.isEmpty(str,true)) column.setAttribute("length",str); 708 709 // type 710 String type = getType(engine,info,cfc,prop,meta,getDefaultTypeForGenerator(engine,generator,foreignCFC)); 711 //print.o(prop.getName()+":"+type+"::"+getDefaultTypeForGenerator(engine,generator,foreignCFC)); 712 if(!StringUtil.isEmpty(type))id.setAttribute("type", type); 713 714 // unsaved-value 715 str=toString(engine,cfc,prop,meta,"unsavedValue"); 716 if(str!=null)id.setAttribute("unsaved-value", str); 717 718 } 719 720 private static String getDefaultTypeForGenerator(HibernateORMEngine engine, String generator,StringBuilder foreignCFC) { 721 String value = getDefaultTypeForGenerator(generator, null); 722 if(value!=null) return value; 723 724 if("foreign".equalsIgnoreCase(generator)) { 725 if(!StringUtil.isEmpty(foreignCFC)) { 726 try { 727 Component cfc = engine.getEntityByCFCName(foreignCFC.toString(), false); 728 if(cfc!=null){ 729 ComponentPro cfcp = ComponentUtil.toComponentPro(cfc); 730 Property[] ids = getIds(engine,cfc,cfcp.getProperties(true),null,true); 731 if(!ArrayUtil.isEmpty(ids)){ 732 Property id = ids[0]; 733 id.getDynamicAttributes(); 734 Struct meta = id.getDynamicAttributes(); 735 if(meta!=null){ 736 String type=Caster.toString(meta.get(KeyImpl.TYPE,null)); 737 738 if(!StringUtil.isEmpty(type) && (!type.equalsIgnoreCase("any") && !type.equalsIgnoreCase("object"))){ 739 return type; 740 } 741 else { 742 String g=Caster.toString(meta.get(GENERATOR,null)); 743 if(!StringUtil.isEmpty(g)){ 744 return getDefaultTypeForGenerator(engine,g,foreignCFC); 745 } 746 } 747 } 748 } 749 } 750 } 751 catch(Throwable t){} 752 } 753 return "string"; 754 } 755 756 return "string"; 757 } 758 759 private static String getDefaultTypeForGenerator(String generator,String defaultValue) { 760 if("increment".equalsIgnoreCase(generator)) return "integer"; 761 if("identity".equalsIgnoreCase(generator)) return "integer"; 762 if("native".equalsIgnoreCase(generator)) return "integer"; 763 if("seqhilo".equalsIgnoreCase(generator)) return "string"; 764 if("uuid".equalsIgnoreCase(generator)) return "string"; 765 if("guid".equalsIgnoreCase(generator)) return "string"; 766 if("select".equalsIgnoreCase(generator)) return "string"; 767 return defaultValue; 768 } 769 770 private static String getType(HibernateORMEngine engine,ColumnInfo info, Component cfc,Property prop,Struct meta,String defaultValue) throws ORMException { 771 // ormType 772 String type = toString(engine,cfc,prop,meta,"ormType"); 773 //type=HibernateCaster.toHibernateType(info,type,null); 774 775 // dataType 776 if(StringUtil.isEmpty(type,true)){ 777 type=toString(engine,cfc,prop,meta,"dataType"); 778 //type=HibernateCaster.toHibernateType(info,type,null); 779 } 780 781 // type 782 if(StringUtil.isEmpty(type,true)){ 783 type=prop.getType(); 784 //type=HibernateCaster.toHibernateType(info,type,null); 785 } 786 787 // type from db info 788 if(StringUtil.isEmpty(type,true)){ 789 if(info!=null){ 790 type=info.getTypeName(); 791 //type=HibernateCaster.toHibernateType(info,type,defaultValue); 792 } 793 else return defaultValue; 794 } 795 796 return HibernateCaster.toHibernateType(info,type,defaultValue); 797 } 798 799 800 801 802 803 804 805 806 807 private static ColumnInfo getColumnInfo(Struct columnsInfo,String tableName,String columnName,ORMEngine engine,ColumnInfo defaultValue) throws ORMException { 808 if(columnsInfo!=null) { 809 ColumnInfo info = (ColumnInfo) columnsInfo.get(KeyImpl.getInstance(columnName),null); 810 if(info==null) return defaultValue; 811 return info; 812 } 813 return defaultValue; 814 } 815 816 /*private static ColumnInfo getColumnInfo(Struct columnsInfo,String tableName,String columnName,ORMEngine engine) throws ORMException { 817 if(columnsInfo!=null) { 818 ColumnInfo info = (ColumnInfo) columnsInfo.get(columnName,null); 819 if(info==null) { 820 String msg="table ["+tableName+"] has no column with name ["+columnName+"]"; 821 if(columnsInfo!=null) 822 msg+=", column names are ["+List.arrayToList(columnsInfo.keysAsString(), ", ")+"]"; 823 ORMUtil.printError(msg, engine); 824 825 //throw new ORMException(msg); 826 } 827 return info; 828 } 829 return null; 830 }*/ 831 832 private static String createXMLMappingGenerator(HibernateORMEngine engine,Element id, PageContext pc,Component cfc,Property prop,StringBuilder foreignCFC) throws PageException { 833 Struct meta = prop.getDynamicAttributes(); 834 835 // generator 836 String className=toString(engine,cfc,prop,meta,"generator"); 837 if(StringUtil.isEmpty(className,true)) return null; 838 839 840 Document doc = XMLUtil.getDocument(id); 841 Element generator = doc.createElement("generator"); 842 id.appendChild(generator); 843 844 generator.setAttribute("class", className); 845 846 //print.e("generator:"+className); 847 848 // params 849 Object obj=meta.get(PARAMS,null); 850 //if(obj!=null){ 851 Struct sct=null; 852 if(obj==null) obj=new StructImpl(); 853 else if(obj instanceof String) obj=convertToSimpleMap((String)obj); 854 855 if(Decision.isStruct(obj)) sct=Caster.toStruct(obj); 856 else throw new HibernateException(engine,cfc,"invalid value for attribute [params] of tag [property]"); 857 className=className.trim().toLowerCase(); 858 859 // special classes 860 if("foreign".equals(className)){ 861 if(!sct.containsKey(PROPERTY)) sct.setEL(PROPERTY, toString(engine,cfc,prop,meta, PROPERTY,true)); 862 863 if(sct.containsKey(PROPERTY)){ 864 String p = Caster.toString(sct.get(PROPERTY),null); 865 if(!StringUtil.isEmpty(p))foreignCFC.append(p); 866 } 867 868 869 } 870 else if("select".equals(className)){ 871 //print.e("select:"+toString(meta, "selectKey",true)); 872 if(!sct.containsKey(KeyImpl.KEY)) sct.setEL(KeyImpl.KEY, toString(engine,cfc,prop,meta, "selectKey",true)); 873 } 874 else if("sequence".equals(className)){ 875 if(!sct.containsKey(SEQUENCE)) sct.setEL(SEQUENCE, toString(engine,cfc,prop,meta, "sequence",true)); 876 } 877 878 Key[] keys = sct.keys(); 879 Element param; 880 for(int y=0;y<keys.length;y++){ 881 882 param = doc.createElement("param"); 883 generator.appendChild(param); 884 885 param.setAttribute( "name", keys[y].getLowerString()); 886 param.appendChild(doc.createTextNode(Caster.toString(sct.get(keys[y])))); 887 888 } 889 //} 890 return className; 891 } 892 893 894 895 896 897 898 899 private static void createXMLMappingProperty(Element clazz, PageContext pc,Component cfc,Property prop,Struct columnsInfo,String tableName,HibernateORMEngine engine) throws ORMException { 900 Struct meta = prop.getDynamicAttributes(); 901 902 903 904 // get table name 905 String columnName=toString(engine,cfc,prop,meta,"column"); 906 if(StringUtil.isEmpty(columnName,true)) columnName=prop.getName(); 907 908 ColumnInfo info=getColumnInfo(columnsInfo,tableName,columnName,engine,null); 909 910 Document doc = XMLUtil.getDocument(clazz); 911 final Element property = doc.createElement("property"); 912 clazz.appendChild(property); 913 914 //name 915 property.setAttribute("name",prop.getName()); 916 917 // type 918 String str = getType(engine,info, cfc,prop, meta, "string"); 919 property.setAttribute("type",str); 920 921 922 923 // formula or column 924 str=toString(engine,cfc,prop,meta,"formula"); 925 Boolean b; 926 if(!StringUtil.isEmpty(str,true)) { 927 property.setAttribute("formula","("+str+")"); 928 } 929 else { 930 //property.setAttribute("column",columnName); 931 932 Element column = doc.createElement("column"); 933 property.appendChild(column); 934 column.setAttribute("name", escape(engine.convertColumnName(columnName))); 935 936 // check 937 str=toString(engine,cfc,prop,meta,"check"); 938 if(!StringUtil.isEmpty(str,true)) column.setAttribute("check",str); 939 940 // default 941 str=toString(engine,cfc,prop,meta,"dbDefault"); 942 if(!StringUtil.isEmpty(str,true)) column.setAttribute("default",str); 943 944 // index 945 str=toString(engine,cfc,prop,meta,"index"); 946 if(!StringUtil.isEmpty(str,true)) column.setAttribute("index",str); 947 948 // length 949 Integer i = toInteger(engine,cfc,meta,"length"); 950 if(i!=null && i>0) column.setAttribute("length",Caster.toString(i.intValue())); 951 952 // not-null 953 b=toBoolean(engine,cfc,meta,"notnull"); 954 if(b!=null && b.booleanValue())column.setAttribute("not-null","true"); 955 956 // precision 957 i=toInteger(engine,cfc,meta,"precision"); 958 if(i!=null && i>-1) column.setAttribute("precision",Caster.toString(i.intValue())); 959 960 // scale 961 i=toInteger(engine,cfc,meta,"scale"); 962 if(i!=null && i>-1) column.setAttribute("scale",Caster.toString(i.intValue())); 963 964 // sql-type 965 str=toString(engine,cfc,prop,meta,"sqltype"); 966 if(!StringUtil.isEmpty(str,true)) column.setAttribute("sql-type",str); 967 968 // unique 969 b=toBoolean(engine,cfc,meta,"unique"); 970 if(b!=null && b.booleanValue())column.setAttribute("unique","true"); 971 972 // unique-key 973 str=toString(engine,cfc,prop,meta,"uniqueKey"); 974 if(StringUtil.isEmpty(str))str=Caster.toString(meta.get(UNIQUE_KEY_NAME,null),null); 975 if(!StringUtil.isEmpty(str,true)) column.setAttribute("unique-key",str); 976 977 978 } 979 980 // generated 981 str=toString(engine,cfc,prop,meta,"generated"); 982 if(!StringUtil.isEmpty(str,true)){ 983 str=str.trim().toLowerCase(); 984 985 if("always".equals(str) || "insert".equals(str) || "never".equals(str)) 986 property.setAttribute("generated",str); 987 else 988 throw invalidValue(engine,cfc,prop,"generated",str,"always,insert,never"); 989 //throw new ORMException(engine,"invalid value ["+str+"] for attribute [generated] of column ["+columnName+"], valid values are [always,insert,never]"); 990 } 991 992 993 // update 994 b=toBoolean(engine,cfc,meta,"update"); 995 if(b!=null && !b.booleanValue())property.setAttribute("update","false"); 996 997 // insert 998 b=toBoolean(engine,cfc,meta,"insert"); 999 if(b!=null && !b.booleanValue())property.setAttribute("insert","false"); 1000 1001 // lazy (dtd defintion:<!ATTLIST property lazy (true|false) "false">) 1002 b=toBoolean(engine,cfc,meta,"lazy"); 1003 if(b!=null && b.booleanValue())property.setAttribute("lazy","true"); 1004 1005 // optimistic-lock 1006 b=toBoolean(engine,cfc,meta,"optimisticlock"); 1007 if(b!=null && !b.booleanValue())property.setAttribute("optimistic-lock","false"); 1008 1009 } 1010 1011 1012 /* 1013 MUST dies kommt aber nicht hier sondern in verarbeitung in component 1014 <cfproperty 1015 persistent="true|false" 1016 > 1017 * */ 1018 private static void createXMLMappingOneToOne(Element clazz, PageContext pc,Component cfc,Property prop,HibernateORMEngine engine) throws PageException { 1019 Struct meta = prop.getDynamicAttributes(); 1020 1021 Boolean b; 1022 1023 Document doc = XMLUtil.getDocument(clazz); 1024 Element x2o; 1025 1026 // column 1027 String fkcolumn=toString(engine,cfc,prop,meta,"fkcolumn"); 1028 String linkTable=toString(engine,cfc,prop,meta,"linkTable"); 1029 1030 1031 if(!StringUtil.isEmpty(linkTable,true) || !StringUtil.isEmpty(fkcolumn,true)) { 1032 clazz=getJoin(clazz); 1033 1034 x2o= doc.createElement("many-to-one"); 1035 //x2o.setAttribute("column", fkcolumn); 1036 x2o.setAttribute("unique", "true"); 1037 1038 if(!StringUtil.isEmpty(linkTable,true)){ 1039 setColumn(engine,doc, x2o, linkTable); 1040 } 1041 else { 1042 setColumn(engine,doc, x2o, fkcolumn); 1043 } 1044 1045 1046 1047 1048 // update 1049 b=toBoolean(engine,cfc,meta,"update"); 1050 if(b!=null)x2o.setAttribute("update",Caster.toString(b.booleanValue())); 1051 1052 // insert 1053 b=toBoolean(engine,cfc,meta,"insert"); 1054 if(b!=null)x2o.setAttribute("insert",Caster.toString(b.booleanValue())); 1055 1056 // not-null 1057 b=toBoolean(engine,cfc,meta,"notNull"); 1058 if(b!=null)x2o.setAttribute("not-null",Caster.toString(b.booleanValue())); 1059 1060 1061 // optimistic-lock 1062 b=toBoolean(engine,cfc,meta,"optimisticLock"); 1063 if(b!=null)x2o.setAttribute("optimistic-lock",Caster.toString(b.booleanValue())); 1064 1065 // not-found 1066 b=toBoolean(engine,cfc,meta, "missingRowIgnored"); 1067 if(b!=null && b.booleanValue()) x2o.setAttribute("not-found", "ignore"); 1068 1069 /* / index 1070 str=toString(meta,"index"); 1071 if(!StringUtil.isEmpty(str,true)) x2o.setAttribute("index", str); 1072 */ 1073 1074 1075 } 1076 else { 1077 x2o= doc.createElement("one-to-one"); 1078 } 1079 clazz.appendChild(x2o); 1080 1081 // access 1082 String str=toString(engine,cfc,prop,meta,"access"); 1083 if(!StringUtil.isEmpty(str,true)) x2o.setAttribute("access", str); 1084 1085 // constrained 1086 b=toBoolean(engine,cfc,meta, "constrained"); 1087 if(b!=null && b.booleanValue()) x2o.setAttribute("constrained", "true"); 1088 1089 // formula 1090 str=toString(engine,cfc,prop,meta,"formula"); 1091 if(!StringUtil.isEmpty(str,true)) x2o.setAttribute("formula", str); 1092 1093 // embed-xml 1094 str=toString(engine,cfc,prop,meta,"embedXml"); 1095 if(!StringUtil.isEmpty(str,true)) x2o.setAttribute("embed-xml", str); 1096 1097 // property-ref 1098 str=toString(engine,cfc,prop,meta,"mappedBy"); 1099 if(!StringUtil.isEmpty(str,true)) x2o.setAttribute("property-ref", str); 1100 1101 // foreign-key 1102 str=toString(engine,cfc,prop,meta,"foreignKeyName"); 1103 if(StringUtil.isEmpty(str,true)) str=toString(engine,cfc,prop,meta,"foreignKey"); 1104 if(!StringUtil.isEmpty(str,true)) x2o.setAttribute("foreign-key", str); 1105 1106 setForeignEntityName(pc,engine,cfc,prop,meta,x2o,true); 1107 1108 createXMLMappingXToX(engine,x2o, pc,cfc,prop,meta); 1109 } 1110 1111 1112 1113 1114 1115 1116 private static Component loadForeignCFC(PageContext pc,HibernateORMEngine engine,Component cfc,Property prop, Struct meta) throws PageException { 1117 // entity 1118 String str=toString(engine,cfc,prop,meta,"entityName"); 1119 Component fcfc=null; 1120 1121 if(!StringUtil.isEmpty(str,true)) { 1122 fcfc = engine.getEntityByEntityName(str, false); 1123 if(fcfc!=null) return fcfc; 1124 } 1125 1126 str = toString(engine,cfc,prop,meta,"cfc",false); 1127 if(!StringUtil.isEmpty(str,true)){ 1128 return engine.getEntityByCFCName(str, false); 1129 } 1130 return null; 1131 } 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 private static void createXMLMappingCollection(Element clazz, PageContext pc,Component cfc,Property prop,ORMConfiguration ormConf, HibernateORMEngine engine) throws PageException { 1142 Struct meta = prop.getDynamicAttributes(); 1143 Document doc = XMLUtil.getDocument(clazz); 1144 Element el=null; 1145 1146 // collection type 1147 String str=prop.getType(); 1148 if(StringUtil.isEmpty(str,true) || "any".equalsIgnoreCase(str) || "object".equalsIgnoreCase(str))str="array"; 1149 else str=str.trim().toLowerCase(); 1150 1151 1152 1153 // bag 1154 if("array".equals(str) || "bag".equals(str)){ 1155 el = doc.createElement("bag"); 1156 } 1157 // map 1158 else if("struct".equals(str) || "map".equals(str)){ 1159 el = doc.createElement("map"); 1160 1161 1162 // map-key 1163 str=toString(engine,cfc,prop,meta,"structKeyColumn",true); 1164 if(!StringUtil.isEmpty(str,true)) { 1165 Element mapKey=doc.createElement("map-key"); 1166 el.appendChild(mapKey); 1167 mapKey.setAttribute("column", str); 1168 1169 // type 1170 str=toString(engine,cfc,prop,meta,"structKeyType"); 1171 if(!StringUtil.isEmpty(str,true))mapKey.setAttribute("type", str); 1172 else mapKey.setAttribute("type", "string"); 1173 } 1174 } 1175 else throw invalidValue(engine,cfc,prop,"collectiontype",str,"array,struct"); 1176 //throw new ORMException(engine,"invalid value ["+str+"] for attribute [collectiontype], valid values are [array,struct]"); 1177 1178 setBeforeJoin(clazz,el); 1179 1180 // name 1181 el.setAttribute("name", prop.getName()); 1182 1183 // table 1184 str=toString(engine,cfc,prop,meta, "table",true); 1185 el.setAttribute("table",escape(engine.convertTableName(str))); 1186 1187 // catalog 1188 str=toString(engine,cfc,prop,meta, "catalog"); 1189 if(!StringUtil.isEmpty(str,true))el.setAttribute("catalog",str); 1190 1191 // schema 1192 str=toString(engine,cfc,prop,meta, "schema"); 1193 if(!StringUtil.isEmpty(str,true))el.setAttribute("schema",str); 1194 1195 // mutable 1196 Boolean b=toBoolean(engine,cfc,meta, "readonly"); 1197 if(b!=null && b.booleanValue()) el.setAttribute("mutable", "false"); 1198 1199 // order-by 1200 str=toString(engine,cfc,prop,meta, "orderby"); 1201 if(!StringUtil.isEmpty(str,true))el.setAttribute("order-by",str); 1202 1203 // element-column 1204 str=toString(engine,cfc,prop,meta,"elementcolumn"); 1205 if(!StringUtil.isEmpty(str,true)){ 1206 Element element = doc.createElement("element"); 1207 el.appendChild(element); 1208 1209 // column 1210 element.setAttribute("column", formatColumn(engine,str)); 1211 1212 // type 1213 str=toString(engine,cfc,prop,meta,"elementtype"); 1214 if(!StringUtil.isEmpty(str,true)) element.setAttribute("type", str); 1215 } 1216 1217 // batch-size 1218 Integer i=toInteger(engine,cfc,meta, "batchsize"); 1219 if(i!=null && i.intValue()>1) el.setAttribute("batch-size", Caster.toString(i.intValue())); 1220 1221 // column 1222 str=toString(engine,cfc,prop,meta,"fkcolumn"); 1223 if(StringUtil.isEmpty(str,true)) str=toString(engine,cfc,prop,meta,"column"); 1224 if(!StringUtil.isEmpty(str,true)){ 1225 Element key = doc.createElement("key"); 1226 XMLUtil.setFirst(el,key); 1227 //el.appendChild(key); 1228 1229 // column 1230 key.setAttribute("column", formatColumn(engine,str)); 1231 1232 // property-ref 1233 str=toString(engine,cfc,prop,meta,"mappedBy"); 1234 if(!StringUtil.isEmpty(str,true)) key.setAttribute("property-ref", str); 1235 } 1236 1237 // cache 1238 setCacheStrategy(engine,cfc,prop,doc, meta, el); 1239 1240 // optimistic-lock 1241 b=toBoolean(engine,cfc,meta, "optimisticlock"); 1242 if(b!=null && !b.booleanValue()) el.setAttribute("optimistic-lock", "false"); 1243 1244 1245 } 1246 1247 1248 private static void setBeforeJoin(Element clazz, Element el) { 1249 Element join; 1250 if(clazz.getNodeName().equals("join")) { 1251 join=clazz; 1252 clazz = getClazz(clazz); 1253 } 1254 else { 1255 join = getJoin(clazz); 1256 } 1257 1258 if(join==clazz) clazz.appendChild(el); 1259 else clazz.insertBefore(el, join); 1260 1261 1262 } 1263 1264 private static Element getClazz(Element join) { 1265 if(join.getNodeName().equals("join")){ 1266 return (Element) join.getParentNode(); 1267 } 1268 return join; 1269 } 1270 1271 private static Element getJoin(Element clazz) { 1272 if(clazz.getNodeName().equals("subclass")){ 1273 NodeList joins = clazz.getElementsByTagName("join"); 1274 if(joins!=null && joins.getLength()>0) 1275 return (Element)joins.item(0); 1276 } 1277 return clazz; 1278 } 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 private static void createXMLMappingManyToMany(Component cfc,HibernateORMEngine engine,PropertyCollection propColl,Element clazz, PageContext pc,Property prop,ORMConfiguration ormConf, DatasourceConnection dc) throws PageException { 1292 Element el = createXMLMappingXToMany(engine,propColl,clazz, pc, cfc,prop); 1293 Struct meta = prop.getDynamicAttributes(); 1294 Document doc = XMLUtil.getDocument(clazz); 1295 Element m2m = doc.createElement("many-to-many"); 1296 el.appendChild(m2m); 1297 1298 // link 1299 setLink(engine,cfc,prop,el,meta,ormConf,true); 1300 1301 setForeignEntityName(pc, engine,cfc,prop, meta, m2m,true); 1302 1303 // order-by 1304 String str = toString(engine,cfc,prop,meta,"orderby"); 1305 if(!StringUtil.isEmpty(str,true))m2m.setAttribute("order-by", str); 1306 1307 // column 1308 str=toString(engine,cfc,prop,meta,"inversejoincolumn"); 1309 1310 // build fkcolumn name 1311 if(StringUtil.isEmpty(str,true)) { 1312 ComponentPro other = (ComponentPro) loadForeignCFC(pc, engine, cfc, prop, meta); 1313 if(other!=null){ 1314 boolean isClass=StringUtil.isEmpty(other.getExtends()); 1315 Property[] _props=getProperties(pc,engine,other,dc,ormConf,meta,isClass); 1316 PropertyCollection _propColl = splitJoins(engine,cfc,new HashMap<String, PropertyCollection>(), _props); 1317 _props=_propColl.getProperties(); 1318 1319 Struct m; 1320 Property _prop=null; 1321 for(int i=0;i<_props.length;i++){ 1322 m = _props[i].getDynamicAttributes(); 1323 // fieldtype 1324 String fieldtype = Caster.toString(m.get(FIELD_TYPE,null),null); 1325 if("many-to-many".equalsIgnoreCase(fieldtype)) { 1326 // linktable 1327 String currLinkTable=Caster.toString(meta.get(LINK_TABLE,null),null); 1328 String othLinkTable=Caster.toString(m.get(LINK_TABLE,null),null); 1329 if(currLinkTable.equals(othLinkTable)) { 1330 // cfc name 1331 ComponentPro cfcp=ComponentUtil.toComponentPro(cfc); 1332 String cfcName=Caster.toString(m.get(CFC,null),null); 1333 if(cfcp.equalTo(cfcName)){ 1334 _prop=_props[i]; 1335 } 1336 } 1337 } 1338 } 1339 str=createM2MFKColumnName(engine, other, _prop, _propColl); 1340 } 1341 } 1342 setColumn(engine,doc, m2m, str); 1343 1344 // not-found 1345 Boolean b=toBoolean(engine,cfc,meta, "missingrowignored"); 1346 if(b!=null && b.booleanValue()) m2m.setAttribute("not-found", "ignore"); 1347 1348 // property-ref 1349 str=toString(engine,cfc,prop,meta,"mappedby"); 1350 if(!StringUtil.isEmpty(str,true)) m2m.setAttribute("property-ref", str); 1351 1352 // foreign-key 1353 str=toString(engine,cfc,prop,meta,"foreignKeyName"); 1354 if(StringUtil.isEmpty(str,true)) str=toString(engine,cfc,prop,meta,"foreignKey"); 1355 if(!StringUtil.isEmpty(str,true)) m2m.setAttribute("foreign-key", str); 1356 } 1357 1358 private static boolean setLink(HibernateORMEngine engine,Component cfc,Property prop,Element el, Struct meta, ORMConfiguration ormConf, boolean linkTableRequired) throws ORMException { 1359 String str=toString(engine,cfc,prop,meta, "linktable",linkTableRequired); 1360 1361 1362 if(!StringUtil.isEmpty(str,true)){ 1363 1364 el.setAttribute("table", escape(engine.convertTableName(str))); 1365 1366 // schema 1367 str=toString(engine,cfc,prop,meta, "linkschema"); 1368 if(StringUtil.isEmpty(str,true)) str=ormConf.getSchema(); 1369 if(!StringUtil.isEmpty(str,true)) el.setAttribute("schema", str); 1370 1371 // catalog 1372 str=toString(engine,cfc,prop,meta, "linkcatalog"); 1373 if(StringUtil.isEmpty(str,true)) str=ormConf.getCatalog(); 1374 if(!StringUtil.isEmpty(str,true)) el.setAttribute("catalog", str); 1375 return true; 1376 } 1377 return false; 1378 } 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 private static void createXMLMappingOneToMany(Component cfc,HibernateORMEngine engine,PropertyCollection propColl,ORMConfiguration ormConf,Element clazz, PageContext pc,Property prop) throws PageException { 1389 Element el = createXMLMappingXToMany(engine,propColl,clazz, pc, cfc,prop); 1390 Struct meta = prop.getDynamicAttributes(); 1391 Document doc = XMLUtil.getDocument(clazz); 1392 Element x2m; 1393 1394 1395 // order-by 1396 String str = toString(engine,cfc,prop,meta,"orderby"); 1397 if(!StringUtil.isEmpty(str,true))el.setAttribute("order-by", str); 1398 1399 // link 1400 if(setLink(engine,cfc,prop,el,meta,ormConf,false)){ 1401 x2m = doc.createElement("many-to-many"); 1402 x2m.setAttribute("unique","true"); 1403 1404 str=toString(engine,cfc,prop,meta,"inversejoincolumn"); 1405 setColumn(engine,doc, x2m, str); 1406 } 1407 else { 1408 x2m = doc.createElement("one-to-many"); 1409 } 1410 el.appendChild(x2m); 1411 1412 1413 // entity-name 1414 1415 setForeignEntityName(pc,engine,cfc,prop,meta,x2m,true); 1416 1417 } 1418 1419 1420 1421 1422 1423 1424 1425 1426 private static Element createXMLMappingXToMany(HibernateORMEngine engine,PropertyCollection propColl,Element clazz, PageContext pc,Component cfc,Property prop) throws PageException { 1427 final Struct meta = prop.getDynamicAttributes(); 1428 Document doc = XMLUtil.getDocument(clazz); 1429 Element el=null; 1430 1431 1432 1433 // collection type 1434 String str=prop.getType(); 1435 if(StringUtil.isEmpty(str,true) || "any".equalsIgnoreCase(str) || "object".equalsIgnoreCase(str))str="array"; 1436 else str=str.trim().toLowerCase(); 1437 1438 Element mapKey=null; 1439 // bag 1440 if("array".equals(str) || "bag".equals(str)){ 1441 el = doc.createElement("bag"); 1442 1443 } 1444 // map 1445 else if("struct".equals(str) || "map".equals(str)){ 1446 el = doc.createElement("map"); 1447 1448 // map-key 1449 mapKey = doc.createElement("map-key"); 1450 //el.appendChild(mapKey); 1451 1452 // column 1453 str=toString(engine,cfc,prop,meta,"structKeyColumn",true); 1454 mapKey.setAttribute("column", formatColumn(engine,str)); 1455 1456 // type 1457 str=toString(engine,cfc,prop,meta,"structKeyType"); 1458 if(!StringUtil.isEmpty(str,true))mapKey.setAttribute("type", str); 1459 else mapKey.setAttribute("type", "string");// MUST get type dynamicly 1460 } 1461 else throw invalidValue(engine,cfc,prop,"collectiontype",str,"array,struct"); 1462 //throw new ORMException(engine,"invalid value ["+str+"] for attribute [collectiontype], valid values are [array,struct]"); 1463 1464 setBeforeJoin(clazz,el); 1465 1466 1467 1468 // batch-size 1469 Integer i=toInteger(engine,cfc,meta, "batchsize"); 1470 if(i!=null){ 1471 if(i.intValue()>1) el.setAttribute("batch-size", Caster.toString(i.intValue())); 1472 } 1473 1474 // cacheUse 1475 setCacheStrategy(engine,cfc,prop,doc, meta, el); 1476 1477 // column 1478 str=createFKColumnName(engine,cfc,prop,propColl); 1479 1480 if(!StringUtil.isEmpty(str,true)){ 1481 Element key = doc.createElement("key"); 1482 el.appendChild(key); 1483 1484 // column 1485 setColumn(engine,doc,key,str); 1486 1487 // property-ref 1488 str=toString(engine,cfc,prop,meta,"mappedBy"); 1489 if(!StringUtil.isEmpty(str,true)) key.setAttribute("property-ref", str); 1490 } 1491 1492 // inverse 1493 Boolean b = toBoolean(engine,cfc,meta, "inverse"); 1494 if(b!=null && b.booleanValue()) el.setAttribute("inverse", "true"); 1495 1496 1497 1498 // mutable 1499 b = toBoolean(engine,cfc,meta, "readonly"); 1500 if(b!=null && b.booleanValue()) el.setAttribute("mutable", "false"); 1501 1502 // optimistic-lock 1503 b=toBoolean(engine,cfc,meta, "optimisticlock"); 1504 if(b!=null && !b.booleanValue()) el.setAttribute("optimistic-lock", "false"); 1505 1506 // where 1507 str=toString(engine,cfc,prop,meta,"where"); 1508 if(!StringUtil.isEmpty(str,true)) el.setAttribute("where", str); 1509 1510 // add map key 1511 if(mapKey!=null)el.appendChild(mapKey); 1512 1513 1514 createXMLMappingXToX(engine,el, pc,cfc,prop,meta); 1515 1516 return el; 1517 } 1518 1519 1520 1521 private static String createFKColumnName(HibernateORMEngine engine, Component cfc, Property prop, PropertyCollection propColl) throws PageException { 1522 1523 1524 // fk column from local defintion 1525 String str=prop==null?null:toString(engine,cfc,prop,prop.getDynamicAttributes(),"fkcolumn"); 1526 if(!StringUtil.isEmpty(str)) 1527 return str; 1528 1529 // no local defintion, get from Foreign enity 1530 Struct meta = prop.getDynamicAttributes(); 1531 String type=toString(engine,cfc,prop,meta,"fieldtype",false); 1532 String otherType; 1533 if("many-to-one".equalsIgnoreCase(type)) otherType="one-to-many"; 1534 else if("one-to-many".equalsIgnoreCase(type)) otherType="many-to-one"; 1535 else return createM2MFKColumnName(engine, cfc, prop, propColl); 1536 1537 String feName = toString(engine,cfc,prop,meta,"cfc",true); 1538 ComponentPro feCFC=(ComponentPro) engine.getEntityByCFCName(feName, false); 1539 Property[] feProps = feCFC.getProperties(true); 1540 1541 Property p; 1542 ComponentPro _cfc; 1543 for(int i=0;i<feProps.length;i++){ 1544 p=feProps[i]; 1545 1546 // compare fieldType 1547 str=toString(engine,feCFC,p,p.getDynamicAttributes(),"fieldtype",false); 1548 if(!otherType.equalsIgnoreCase(str)) continue; 1549 1550 // compare cfc 1551 str=toString(engine,feCFC,p,p.getDynamicAttributes(),"cfc",false); 1552 if(StringUtil.isEmpty(str)) continue; 1553 _cfc=(ComponentPro) engine.getEntityByCFCName(str, false); 1554 if(_cfc==null || !_cfc.equals(cfc))continue; 1555 1556 // get fkcolumn 1557 str=toString(engine,_cfc,p,p.getDynamicAttributes(),"fkcolumn"); 1558 if(!StringUtil.isEmpty(str)) return str; 1559 1560 1561 } 1562 throw new ORMException(engine, "cannot terminate forgein key column name"); 1563 } 1564 1565 1566 private static String createM2MFKColumnName(HibernateORMEngine engine, Component cfc, Property prop, PropertyCollection propColl) throws ORMException { 1567 1568 String str=prop==null?null:toString(engine,cfc,prop,prop.getDynamicAttributes(),"fkcolumn"); 1569 if(StringUtil.isEmpty(str)){ 1570 Property[] ids = getIds(engine,cfc,propColl); 1571 if(ids.length==1) { 1572 str=toString(engine,cfc,ids[0],ids[0].getDynamicAttributes(),"column"); 1573 if(StringUtil.isEmpty(str,true)) str=ids[0].getName(); 1574 } 1575 else if(prop!=null)str=toString(engine,cfc,prop,prop.getDynamicAttributes(),"fkcolumn",true); 1576 else 1577 throw new ORMException(engine, "cannot terminate forgein key column name"); 1578 1579 str=HibernateCaster.getEntityName(cfc)+"_"+str; 1580 } 1581 return str; 1582 } 1583 1584 private static void setForeignEntityName(PageContext pc,HibernateORMEngine engine,Component cfc,Property prop, Struct meta, Element el, boolean cfcRequired) throws PageException { 1585 // entity 1586 String str=cfcRequired?null:toString(engine,cfc,prop,meta,"entityName"); 1587 if(!StringUtil.isEmpty(str,true)) { 1588 el.setAttribute("entity-name", str); 1589 } 1590 else { 1591 // cfc 1592 //createFKColumnName(engine, cfc, prop, propColl); 1593 1594 str = toString(engine,cfc,prop,meta,"cfc",cfcRequired); 1595 if(!StringUtil.isEmpty(str,true)){ 1596 Component _cfc=engine.getEntityByCFCName(str, false); 1597 str=HibernateCaster.getEntityName(_cfc); 1598 el.setAttribute("entity-name", str); 1599 } 1600 } 1601 } 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 private static void setCacheStrategy(HibernateORMEngine engine,Component cfc,Property prop,Document doc,Struct meta, Element el) throws ORMException { 1612 String strategy = toString(engine,cfc,prop,meta,"cacheuse"); 1613 1614 if(!StringUtil.isEmpty(strategy,true)){ 1615 strategy=strategy.trim().toLowerCase(); 1616 if("read-only".equals(strategy) || "nonstrict-read-write".equals(strategy) || "read-write".equals(strategy) || "transactional".equals(strategy)){ 1617 Element cache = doc.createElement("cache"); 1618 XMLUtil.setFirst(el, cache); 1619 el.appendChild(cache); 1620 cache.setAttribute("usage", strategy); 1621 String name = toString(engine,cfc,prop,meta,"cacheName"); 1622 if(!StringUtil.isEmpty(name,true)){ 1623 cache.setAttribute("region", name); 1624 } 1625 } 1626 else 1627 throw new HibernateException(engine,cfc,"invalid value ["+strategy+"] for attribute [cacheuse], valid values are [read-only,nonstrict-read-write,read-write,transactional]"); 1628 } 1629 1630 } 1631 1632 1633 1634 1635 1636 1637 1638 private static void setColumn(HibernateORMEngine engine,Document doc, Element el, String columnValue) throws PageException { 1639 if(StringUtil.isEmpty(columnValue,true)) return; 1640 1641 String[] arr = List.toStringArray(List.listToArray(columnValue, ',')); 1642 if(arr.length==1){ 1643 el.setAttribute("column", formatColumn(engine,arr[0])); 1644 } 1645 else { 1646 Element column; 1647 for(int i=0;i<arr.length;i++){ 1648 column=doc.createElement("column"); 1649 el.appendChild(column); 1650 column.setAttribute("name", formatColumn(engine,arr[i])); 1651 } 1652 } 1653 } 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 private static void createXMLMappingManyToOne(Element clazz, PageContext pc,Component cfc,Property prop, HibernateORMEngine engine, PropertyCollection propColl) throws PageException { 1664 Struct meta = prop.getDynamicAttributes(); 1665 Boolean b; 1666 1667 Document doc = XMLUtil.getDocument(clazz); 1668 clazz=getJoin(clazz); 1669 1670 Element m2o = doc.createElement("many-to-one"); 1671 clazz.appendChild(m2o); 1672 1673 // columns 1674 String linktable = toString(engine,cfc,prop,meta,"linktable"); 1675 String _columns; 1676 if(!StringUtil.isEmpty(linktable,true)) _columns=toString(engine,cfc,prop,meta,"inversejoincolumn"); 1677 else _columns=createFKColumnName(engine, cfc, prop, propColl);//toString(engine,cfc,prop,meta,"fkcolumn"); 1678 setColumn(engine,doc, m2o, _columns); 1679 1680 // cfc 1681 setForeignEntityName(pc,engine,cfc,prop,meta,m2o,true); 1682 1683 // column 1684 //String str=toString(prop,meta,"column",true); 1685 //m2o.setAttribute("column", str); 1686 1687 // insert 1688 b=toBoolean(engine,cfc,meta, "insert"); 1689 if(b!=null && !b.booleanValue()) m2o.setAttribute("insert", "false"); 1690 1691 // update 1692 b=toBoolean(engine,cfc,meta, "update"); 1693 if(b!=null && !b.booleanValue()) m2o.setAttribute("update", "false"); 1694 1695 // property-ref 1696 String str=toString(engine,cfc,prop,meta,"mappedBy"); 1697 if(!StringUtil.isEmpty(str,true)) m2o.setAttribute("property-ref", str); 1698 1699 // update 1700 b=toBoolean(engine,cfc,meta, "unique"); 1701 if(b!=null && b.booleanValue()) m2o.setAttribute("unique", "true"); 1702 1703 // not-null 1704 b=toBoolean(engine,cfc,meta, "notnull"); 1705 if(b!=null && b.booleanValue()) m2o.setAttribute("not-null", "true"); 1706 1707 // optimistic-lock 1708 b=toBoolean(engine,cfc,meta, "optimisticLock"); 1709 if(b!=null && !b.booleanValue()) m2o.setAttribute("optimistic-lock", "false"); 1710 1711 // not-found 1712 b=toBoolean(engine,cfc,meta, "missingRowIgnored"); 1713 if(b!=null && b.booleanValue()) m2o.setAttribute("not-found", "ignore"); 1714 1715 // index 1716 str=toString(engine,cfc,prop,meta,"index"); 1717 if(!StringUtil.isEmpty(str,true)) m2o.setAttribute("index", str); 1718 1719 // unique-key 1720 str=toString(engine,cfc,prop,meta,"uniqueKeyName"); 1721 if(StringUtil.isEmpty(str,true))str=toString(engine,cfc,prop,meta,"uniqueKey"); 1722 if(!StringUtil.isEmpty(str,true)) m2o.setAttribute("unique-key", str); 1723 1724 // foreign-key 1725 str=toString(engine,cfc,prop,meta,"foreignKeyName"); 1726 if(StringUtil.isEmpty(str,true)) str=toString(engine,cfc,prop,meta,"foreignKey"); 1727 if(!StringUtil.isEmpty(str,true)) m2o.setAttribute("foreign-key", str); 1728 1729 // access 1730 str=toString(engine,cfc,prop,meta,"access"); 1731 if(!StringUtil.isEmpty(str,true)) m2o.setAttribute("access", str); 1732 1733 createXMLMappingXToX(engine,m2o, pc,cfc,prop,meta); 1734 1735 } 1736 1737 1738 1739 1740 1741 1742 1743 1744 private static String formatColumn(HibernateORMEngine engine,String name) { 1745 name=name.trim(); 1746 return escape(engine.convertColumnName(name)); 1747 } 1748 1749 /* 1750 1751 1752 <cfproperty 1753 cfc="Referenced_CFC_Name" 1754 linktable="Link table name" 1755 linkcatalog="Catalog for the link table" 1756 linkschema="Schema for the link table" 1757 fkcolumn="Foreign Key column name" 1758 inversejoincolumn="Column name or comma-separated list of primary key columns" 1759 1760 1761 > 1762 1763 */ 1764 private static void createXMLMappingXToX(HibernateORMEngine engine,Element x2x, PageContext pc, Component cfc,Property prop, Struct meta) throws ORMException { 1765 x2x.setAttribute("name",prop.getName()); 1766 1767 // cascade 1768 String str=toString(engine,cfc,prop,meta,"cascade"); 1769 if(!StringUtil.isEmpty(str,true)) x2x.setAttribute("cascade", str); 1770 1771 // fetch 1772 str=toString(engine,cfc,prop,meta,"fetch"); 1773 if(!StringUtil.isEmpty(str,true)) { 1774 str=str.trim().toLowerCase(); 1775 if("join".equals(str) || "select".equals(str)) 1776 x2x.setAttribute("fetch", str); 1777 else 1778 throw invalidValue(engine,cfc,prop,"fetch",str,"join,select"); 1779 //throw new ORMException(engine,"invalid value ["+str+"] for attribute [fetch], valid values are [join,select]"); 1780 } 1781 1782 // lazy 1783 setLazy(engine,cfc,prop,meta,x2x); 1784 1785 } 1786 1787 1788 1789 1790 1791 private static void setLazy(HibernateORMEngine engine, Component cfc,Property prop, Struct meta, Element x2x) throws ORMException { 1792 String str = toString(engine,cfc,prop,meta, "lazy"); 1793 if(!StringUtil.isEmpty(str,true)){ 1794 str=str.trim(); 1795 String name=x2x.getNodeName(); 1796 Boolean b = Caster.toBoolean(str,null); 1797 1798 // <!ATTLIST many-to-one lazy (false|proxy|no-proxy) #IMPLIED> 1799 // <!ATTLIST one-to-one lazy (false|proxy|no-proxy) #IMPLIED> 1800 if("many-to-one".equals(name) || "one-to-one".equals(name)) { 1801 if(b!=null) x2x.setAttribute("lazy", b.booleanValue()?"proxy":"false"); 1802 else if("proxy".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "proxy"); 1803 else if("no-proxy".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "no-proxy"); 1804 else throw invalidValue(engine,cfc,prop,"lazy",str,"true,false,proxy,no-proxy"); 1805 } 1806 1807 1808 // <!ATTLIST many-to-many lazy (false|proxy) #IMPLIED> 1809 // <!ATTLIST key-many-to-one lazy (false|proxy) #IMPLIED> 1810 else if("many-to-many".equals(name) || "key-many-to-one".equals(name)) { 1811 if(b!=null) x2x.setAttribute("lazy", b.booleanValue()?"proxy":"false"); 1812 else if("proxy".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "proxy"); 1813 throw invalidValue(engine,cfc,prop,"lazy",str,"true,false,proxy"); 1814 1815 } 1816 1817 else { 1818 if(b!=null) x2x.setAttribute("lazy", b.booleanValue()?"true":"false"); 1819 else if("extra".equalsIgnoreCase(str)) x2x.setAttribute("lazy", "extra"); 1820 else throw invalidValue(engine,cfc,prop,"lazy",str,"true,false,extra"); 1821 } 1822 } 1823 } 1824 1825 private static void createXMLMappingTimestamp(HibernateORMEngine engine,Element clazz, PageContext pc,Component cfc,Property prop) throws PageException { 1826 Struct meta = prop.getDynamicAttributes(); 1827 String str; 1828 Boolean b; 1829 1830 1831 Document doc = XMLUtil.getDocument(clazz); 1832 Element timestamp = doc.createElement("timestamp"); 1833 clazz.appendChild(timestamp); 1834 1835 timestamp.setAttribute("name",prop.getName()); 1836 1837 // access 1838 str=toString(engine,cfc,prop,meta,"access"); 1839 if(!StringUtil.isEmpty(str,true))timestamp.setAttribute("access", str); 1840 1841 // column 1842 str=toString(engine,cfc,prop,meta,"column"); 1843 if(StringUtil.isEmpty(str,true)) str=prop.getName(); 1844 timestamp.setAttribute("column",formatColumn(engine,str)); 1845 1846 // generated 1847 b=toBoolean(engine,cfc,meta, "generated"); 1848 if(b!=null) timestamp.setAttribute("generated", b.booleanValue()?"always":"never"); 1849 1850 // source 1851 str=toString(engine,cfc,prop,meta,"source"); 1852 if(!StringUtil.isEmpty(str,true)) { 1853 str=str.trim().toLowerCase(); 1854 if("db".equals(str) || "vm".equals(str)) 1855 timestamp.setAttribute("source", str); 1856 else 1857 throw invalidValue(engine,cfc,prop,"source",str,"db,vm"); 1858 } 1859 1860 // unsavedValue 1861 str=toString(engine,cfc,prop,meta,"unsavedValue"); 1862 if(!StringUtil.isEmpty(str,true)) { 1863 str=str.trim().toLowerCase(); 1864 if("null".equals(str) || "undefined".equals(str)) 1865 timestamp.setAttribute("unsaved-value", str); 1866 else 1867 throw invalidValue(engine,cfc,prop,"unsavedValue",str,"null, undefined"); 1868 //throw new ORMException(engine,"invalid value ["+str+"] for attribute [unsavedValue], valid values are [null, undefined]"); 1869 } 1870 } 1871 1872 1873 private static ORMException invalidValue(HibernateORMEngine engine,Component cfc,Property prop, String attrName, String invalid, String valid) { 1874 String owner = prop.getOwnerName(); 1875 if(StringUtil.isEmpty(owner))return new HibernateException(engine,cfc,"invalid value ["+invalid+"] for attribute ["+attrName+"] of property ["+prop.getName()+"], valid values are ["+valid+"]"); 1876 return new HibernateException(engine,cfc,"invalid value ["+invalid+"] for attribute ["+attrName+"] of property ["+prop.getName()+"] of Component ["+List.last(owner,'.')+"], valid values are ["+valid+"]"); 1877 } 1878 1879 1880 1881 1882 1883 1884 private static void createXMLMappingVersion(HibernateORMEngine engine,Element clazz, PageContext pc,Component cfc,Property prop) throws PageException { 1885 Struct meta = prop.getDynamicAttributes(); 1886 1887 Document doc = XMLUtil.getDocument(clazz); 1888 Element version = doc.createElement("version"); 1889 clazz.appendChild(version); 1890 1891 1892 version.setAttribute("name",prop.getName()); 1893 1894 // column 1895 String str = toString(engine,cfc,prop,meta,"column"); 1896 if(StringUtil.isEmpty(str,true)) str=prop.getName(); 1897 version.setAttribute("column",formatColumn(engine,str)); 1898 1899 // access 1900 str=toString(engine,cfc,prop,meta,"access"); 1901 if(!StringUtil.isEmpty(str,true))version.setAttribute("access", str); 1902 1903 // generated 1904 Object o=meta.get(GENERATED,null); 1905 if(o!=null){ 1906 Boolean b = Caster.toBoolean(o,null); 1907 str=null; 1908 if(b!=null) { 1909 str=b.booleanValue()?"always":"never"; 1910 } 1911 else { 1912 str=Caster.toString(o,null); 1913 if("always".equalsIgnoreCase(str))str="always"; 1914 else if("never".equalsIgnoreCase(str))str="never"; 1915 else throw invalidValue(engine,cfc,prop,"generated",o.toString(),"true,false,always,never"); 1916 //throw new ORMException(engine,"invalid value ["+o+"] for attribute [generated] of property ["+prop.getName()+"], valid values are [true,false,always,never]"); 1917 } 1918 version.setAttribute( "generated", str); 1919 } 1920 1921 // insert 1922 Boolean b = toBoolean(engine,cfc,meta, "insert"); 1923 if(b!=null && !b.booleanValue()) version.setAttribute("insert", "false"); 1924 1925 // type 1926 String typeName="dataType"; 1927 str=toString(engine,cfc,prop,meta,typeName); 1928 if(StringUtil.isEmpty(str,true)){ 1929 typeName="ormType"; 1930 str=toString(engine,cfc,prop,meta,typeName); 1931 } 1932 if(!StringUtil.isEmpty(str,true)) { 1933 str=str.trim().toLowerCase(); 1934 if("int".equals(str) || "integer".equals(str)) 1935 version.setAttribute("type", "integer"); 1936 else if("long".equals(str)) 1937 version.setAttribute("type", "long"); 1938 else if("short".equals(str)) 1939 version.setAttribute("type", "short"); 1940 else 1941 throw invalidValue(engine,cfc,prop,typeName,str,"int,integer,long,short"); 1942 //throw new ORMException(engine,"invalid value ["+str+"] for attribute ["+typeName+"], valid values are [int,integer,long,short]"); 1943 } 1944 else 1945 version.setAttribute("type", "integer"); 1946 1947 // unsavedValue 1948 str=toString(engine,cfc,prop,meta,"unsavedValue"); 1949 if(!StringUtil.isEmpty(str,true)) { 1950 str=str.trim().toLowerCase(); 1951 if("null".equals(str) || "negative".equals(str) || "undefined".equals(str)) 1952 version.setAttribute("unsaved-value", str); 1953 else 1954 throw invalidValue(engine,cfc,prop,"unsavedValue",str,"null, negative, undefined"); 1955 //throw new ORMException(engine,"invalid value ["+str+"] for attribute [unsavedValue], valid values are [null, negative, undefined]"); 1956 } 1957 } 1958 1959 1960 public static Struct convertToSimpleMap(String paramsStr) { 1961 paramsStr=paramsStr.trim(); 1962 if(!StringUtil.startsWith(paramsStr, '{') || !StringUtil.endsWith(paramsStr, '}')) 1963 return null; 1964 1965 paramsStr = paramsStr.substring(1, paramsStr.length() - 1); 1966 String items[] = List.listToStringArray(paramsStr, ','); 1967 1968 Struct params=new StructImpl(); 1969 String arr$[] = items; 1970 int index; 1971 for(int i = 0; i < arr$.length; i++) { 1972 String pair = arr$[i]; 1973 index = pair.indexOf('='); 1974 if(index == -1) return null; 1975 1976 params.setEL( 1977 KeyImpl.init(deleteQuotes(pair.substring(0, index).trim()).trim()), 1978 deleteQuotes(pair.substring(index + 1).trim())); 1979 } 1980 1981 return params; 1982 } 1983 1984 private static String deleteQuotes(String str) { 1985 if(StringUtil.isEmpty(str,true))return ""; 1986 char first=str.charAt(0); 1987 if((first=='\'' || first=='"') && StringUtil.endsWith(str, first)) 1988 return str.substring(1, str.length() - 1); 1989 return str; 1990 } 1991 1992 1993 private static String toString(HibernateORMEngine engine,Component cfc,Property prop,Struct sct, String key) throws ORMException { 1994 return toString(engine,cfc,prop,sct, key, false); 1995 } 1996 1997 private static String toString(HibernateORMEngine engine,Component cfc,Property prop,Struct sct, String key, boolean throwErrorWhenNotExist) throws ORMException { 1998 return toString(engine,cfc,prop,sct, KeyImpl.init(key), throwErrorWhenNotExist); 1999 } 2000 2001 private static String toString(HibernateORMEngine engine,Component cfc,Property prop,Struct sct, Collection.Key key, boolean throwErrorWhenNotExist) throws ORMException { 2002 Object value = sct.get(key,null); 2003 if(value==null) { 2004 if(throwErrorWhenNotExist){ 2005 if(prop==null)throw new HibernateException(engine,cfc,"attribute ["+key+"] is required"); 2006 throw new HibernateException(engine,cfc,"attribute ["+key+"] of property ["+prop.getName()+"] of Component ["+_getCFCName(prop)+"] is required"); 2007 } 2008 return null; 2009 } 2010 2011 String str=Caster.toString(value,null); 2012 if(str==null) { 2013 if(prop==null) 2014 throw new HibernateException(engine,cfc,"invalid type ["+Caster.toTypeName(value)+"] for attribute ["+key+"], value must be a string"); 2015 throw new HibernateException(engine,cfc,"invalid type ["+Caster.toTypeName(value)+"] for attribute ["+key+"] of property ["+prop.getName()+"] of Component ["+_getCFCName(prop)+"], value must be a string"); 2016 } 2017 return str; 2018 } 2019 2020 private static String _getCFCName(Property prop) { 2021 String owner = prop.getOwnerName(); 2022 return List.last(owner,'.'); 2023 } 2024 2025 2026 2027 2028 private static Boolean toBoolean(HibernateORMEngine engine,Component cfc,Struct sct, String key) throws ORMException { 2029 Object value = sct.get(KeyImpl.init(key),null); 2030 if(value==null) return null; 2031 2032 Boolean b=Caster.toBoolean(value,null); 2033 if(b==null) throw new HibernateException(engine,cfc,"invalid type ["+Caster.toTypeName(value)+"] for attribute ["+key+"], value must be a boolean"); 2034 return b; 2035 } 2036 2037 private static Integer toInteger(HibernateORMEngine engine,Component cfc,Struct sct, String key) throws ORMException { 2038 Object value = sct.get(KeyImpl.init(key),null); 2039 if(value==null) return null; 2040 2041 Integer i=Caster.toInteger(value,null); 2042 if(i==null) throw new HibernateException(engine,cfc,"invalid type ["+Caster.toTypeName(value)+"] for attribute ["+key+"], value must be a numeric value"); 2043 return i; 2044 } 2045 2046 2047 } 2048 2049 class PropertyCollection { 2050 private Property[] properties; 2051 private String tableName; 2052 public PropertyCollection(String tableName,Property[] properties) { 2053 this.tableName=tableName; 2054 this.properties=properties; 2055 } 2056 public PropertyCollection(String tableName, java.util.List<Property> properties) { 2057 this.tableName=tableName; 2058 this.properties=properties.toArray(new Property[properties.size()]); 2059 } 2060 public Property[] getProperties() { 2061 return properties; 2062 } 2063 public String getTableName() { 2064 return tableName; 2065 } 2066 2067 }