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