| 1 18 package org.objectweb.speedo.generation.jorm.rdb; 19 20 import org.objectweb.jorm.api.PException; 21 import org.objectweb.jorm.lib.JormPathHelper; 22 import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMapping; 23 import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMultiMapping; 24 import org.objectweb.jorm.mapper.rdb.metainfo.RdbExternalTable; 25 import org.objectweb.jorm.mapper.rdb.metainfo.RdbGenClassMapping; 26 import org.objectweb.jorm.mapper.rdb.metainfo.RdbJoin; 27 import org.objectweb.jorm.mapper.rdb.metainfo.RdbPrimitiveElementMapping; 28 import org.objectweb.jorm.mapper.rdb.metainfo.RdbTable; 29 import org.objectweb.jorm.metainfo.api.Class; 30 import org.objectweb.jorm.metainfo.api.ClassMapping; 31 import org.objectweb.jorm.metainfo.api.ClassRef; 32 import org.objectweb.jorm.metainfo.api.CommonClassMapping; 33 import org.objectweb.jorm.metainfo.api.GenClassMapping; 34 import org.objectweb.jorm.metainfo.api.GenClassRef; 35 import org.objectweb.jorm.metainfo.api.Manager; 36 import org.objectweb.jorm.metainfo.api.Mapping; 37 import org.objectweb.jorm.metainfo.api.MetaObject; 38 import org.objectweb.jorm.metainfo.api.NameDef; 39 import org.objectweb.jorm.metainfo.api.PrimitiveElement; 40 import org.objectweb.jorm.metainfo.api.PrimitiveElementMapping; 41 import org.objectweb.jorm.metainfo.api.TypedElement; 42 import org.objectweb.jorm.util.api.Loggable; 43 import org.objectweb.speedo.api.SpeedoException; 44 import org.objectweb.speedo.api.SpeedoProperties; 45 import org.objectweb.speedo.generation.jorm.JormMIMappingBuilder; 46 import org.objectweb.speedo.metadata.SpeedoClass; 47 import org.objectweb.speedo.metadata.SpeedoCollection; 48 import org.objectweb.speedo.metadata.SpeedoElement; 49 import org.objectweb.speedo.metadata.SpeedoExtension; 50 import org.objectweb.speedo.metadata.SpeedoField; 51 import org.objectweb.speedo.metadata.SpeedoMap; 52 import org.objectweb.util.monolog.api.BasicLevel; 53 import org.objectweb.util.monolog.api.Logger; 54 import org.objectweb.util.monolog.api.LoggerFactory; 55 56 import java.util.HashMap ; 57 import java.util.Iterator ; 58 import java.util.Map ; 59 import java.util.StringTokenizer ; 60 61 68 public class OneTableRdbJormIMappingBuilder 69 implements JormMIMappingBuilder, SpeedoProperties, Loggable { 70 71 private final static String CLASS_MAPPING_RULE_NAME = "multi-table"; 72 private final static String GENCLASS_MAPPING_RULE_NAME = "to-table"; 73 74 private Logger logger; 75 private boolean debug = false; 76 77 80 public Logger getLogger() { 81 return logger; 82 } 83 84 public LoggerFactory getLoggerFactory() { 85 return null; 86 } 87 88 public void setLogger(Logger logger) { 89 this.logger = logger; 90 debug = logger != null && logger.isLoggable(BasicLevel.DEBUG); 91 } 92 93 public void setLoggerFactory(LoggerFactory loggerFactory) { 94 if (logger == null && loggerFactory != null) { 95 setLogger(loggerFactory.getLogger( 96 SpeedoProperties.LOGGER_NAME 97 + ".generation.jorm.mimappingbuilder")); 98 } 99 } 100 101 104 113 public ClassMapping createClassMapping(Class clazz, 114 SpeedoClass sc, 115 Mapping mapping) 116 throws PException, SpeedoException { 117 RdbClassMultiMapping rcm = new RdbClassMultiMapping( 118 CLASS_MAPPING_RULE_NAME, clazz, mapping); 119 mapping.setClassMapping(rcm); 120 rcm.createRdbTable(getTableName(sc)); 121 return rcm; 122 } 123 124 public void finalizeClassMapping(SpeedoClass sc, 125 String projectName, 126 String mapperName) 127 throws PException, SpeedoException { 128 RdbClassMultiMapping rcm = (RdbClassMultiMapping) sc.jormclass 129 .getClassProject(projectName).getMapping(mapperName).getClassMapping(); 130 if (sc.superClassName != null) { 131 String ruleName; 132 String im = sc.getExtensionValueByKey(SpeedoProperties.INHERITANCE_MAPPING); 133 if (im == null) { 134 throw new SpeedoException( 135 "No inheritance mapping defined for the class '" + sc.getFQName() +"'"); 136 } else if (SpeedoProperties.INHERITANCE_FILTERED_MAPPING.equals(im)) { 137 138 ruleName = RdbClassMapping.MAP_NEW_FIELDS_TO_EXTENDED_STRUCTURES; 139 } else if (SpeedoProperties.INHERITANCE_HORIZONTAL_MAPPING.equals(im)) { 140 ruleName = RdbClassMapping.REMAP_FIELDS_TO_NEW_STRUCTURES; 141 } else if (SpeedoProperties.INHERITANCE_VERTICAL_MAPPING.equals(im)) { 142 ruleName = RdbClassMapping.MAP_NEW_FIELDS_TO_ADDED_STRUCTURES; 143 throw new SpeedoException("The vertical mapping for the inheritance is not supported currently"); 146 } else { 147 throw new SpeedoException("Inheritance mapping type is unknown (" 148 + im + ") for the class '" + sc.getFQName() +"'"); 149 } 150 SpeedoClass parent = sc.getSpeedoClassFromContext(sc.superClassName); 151 rcm.createParentClassMapping(ruleName, sc.jormclass.getSuperClass(parent.getFQName())); 152 if (debug) { 154 logger.log(BasicLevel.DEBUG, "Add dependencies between " 155 + parent.getFQName() + " and " + sc.getFQName()); 156 } 157 rcm.addDependency(parent.getFQName()); 158 parent.jormclass.getClassProject(projectName) 159 .getMapping(mapperName).getClassMapping().addDependency(sc.getFQName()); 160 } 161 } 162 163 172 public GenClassMapping createGenClassMapping(GenClassRef gcr, 173 SpeedoField sf, 174 Mapping mapping) 175 throws PException, SpeedoException { 176 RdbGenClassMapping rgcm = new RdbGenClassMapping( 177 GENCLASS_MAPPING_RULE_NAME, gcr, mapping); 178 mapping.addGenClassMapping(gcr.getGenClassId(), rgcm); 179 SpeedoExtension se = sf.getExtension(VENDOR_NAME, JOIN_TABLE); 180 if (se != null) { 181 rgcm.createRdbTable(se.value); 182 se = sf.getExtensionByKey(REVERSE_FIELD); 183 if (se != null) { 184 String cn = null; 185 if (sf.jdoTuple instanceof SpeedoCollection) { 186 cn = (String ) ((SpeedoCollection) sf.jdoTuple).elementType; 187 } else if (sf.jdoTuple instanceof SpeedoMap) { 188 cn = (String ) ((SpeedoMap) sf.jdoTuple).valueType; 189 } 190 SpeedoClass sc = sf.jdoClass.jdoPackage.jdoXMLDescriptor.smi. 191 getSpeedoClass(cn, sf.jdoClass.jdoPackage); 192 SpeedoField sf2 = (SpeedoField) sc.jdoField.get(se.value); 193 Class c = ((Manager) gcr.getParent().getParent().getParent()) 194 .getClass(sc.getFQName()); 195 TypedElement te = c.getTypedElement(sf2.name); 196 if (te instanceof GenClassRef) { 197 rgcm.getRdbTable().setReadOnly(true); 198 logger.log(BasicLevel.DEBUG, "field '" + sf.name + "' is read only"); 199 } 200 } 202 } else if (gcr.isClassRef() 203 && sf.getExtension(VENDOR_NAME, SOURCE_FK) != null 204 && sf.getExtension(VENDOR_NAME, TARGET_FK) == null) { 205 SpeedoClass tsc = sf.jdoClass.jdoPackage.jdoXMLDescriptor 207 .getSpeedoClass(gcr.getClassRef().getMOClass().getFQName(), true); 208 se = (tsc == null ? null : tsc.getExtensionByKey(SQL_NAME)); 209 Manager mgr = getManager(gcr); 210 Class tclazz = mgr.getClass(tsc.getFQName()); 211 RdbClassMultiMapping trcm = (RdbClassMultiMapping) 212 tclazz.getClassProject(mapping.getClassMapping().getProjectName()) 213 .getMapping(mapping.getMapperName()).getClassMapping(); 214 RdbTable t = rgcm.createRdbTable( 215 (se == null ? getTableName(tsc) : se.value)); 216 t.setColocated(true); 218 se = sf.getExtensionByKey(REVERSE_FIELD); 219 if (se != null) { 220 logger.log(BasicLevel.DEBUG, "REVERSE-FIELD(" + sf.name + "):" + se.value); 221 t.setReadOnly(true); 224 } else { 225 logger.log(BasicLevel.DEBUG, "No REVERSE-FIELD(" + sf.name + ")"); 226 trcm.getRdbTable().setColocated(true); 227 trcm.getRdbTable().setColocatedMaster(true); 228 } 229 trcm.addDependency(sf.jdoClass.getFQName()); 230 mapping.getClassMapping().addDependency(tclazz.getFQName()); 231 } else { 232 rgcm.createRdbTable(getTableName(gcr)); 234 } 235 return rgcm; 236 } 237 238 248 public PrimitiveElementMapping createFieldMapping(PrimitiveElement pe, 249 SpeedoElement selem, 250 CommonClassMapping cm) 251 throws PException { 252 RdbTable t; 253 boolean ingc = false; 254 String extensionColName = SQL_NAME; 255 String extensionColType = SQL_TYPE; 256 if (cm instanceof RdbClassMultiMapping) { 257 t = ((RdbClassMultiMapping) cm).getRdbTable(); 258 } else if (cm instanceof RdbGenClassMapping) { 259 ingc = true; 260 GenClassRef gcr = (GenClassRef) pe.getParent(); 261 if (gcr.getPrimitiveElement() == pe) { 262 extensionColName = ELEMENT; 263 extensionColType = ELEMENT_TYPE; 264 } else { 265 Iterator it = gcr.getIndexFields().iterator(); 266 if (it.hasNext() && pe == it.next()) { 267 extensionColName = INDEX; 268 extensionColType = INDEX_TYPE; 269 } 270 } 271 t = ((RdbGenClassMapping) cm).getRdbTable(); 272 } else { 273 new Exception ().printStackTrace(); 274 throw new PException("Unmanaged HelperClassMapping: " + cm); 275 } 276 String colName = getColumnName(pe); 277 String colType = null; 278 if (selem != null) { 279 if (selem instanceof SpeedoClass) { 280 extensionColName = pe.getName() + '-' + extensionColName; 282 extensionColType = pe.getName() + '-' + extensionColType; 283 } else if (selem instanceof SpeedoField 284 && ((SpeedoField) selem).jdoTuple instanceof SpeedoMap 285 && selem.getExtensionValueByKey(KEY_FIELD) != null 286 ) { 287 288 } 289 SpeedoExtension seColName = selem.getExtensionByKey(extensionColName); 290 if (seColName != null) { 291 colName = seColName.value; 292 } 293 SpeedoExtension seColType = selem.getExtensionByKey(extensionColType); 294 if (seColType != null) { 295 colType = seColType.value; 296 } 297 } 298 return t.createPrimitiveElementMapping(pe,colName, colType, false); 299 } 300 301 309 public void createNameDefMapping(CommonClassMapping cm, 310 NameDef nd, 311 SpeedoClass sc, 312 boolean isIdentifier, 313 boolean isInGenClass) 314 throws PException, SpeedoException { 315 if (debug) { 316 logger.log(BasicLevel.DEBUG, "RdbMapping: createNameDefMapping " 317 + "\n\tnd=" + nd 318 + "\n\tsc=" + (sc == null ? null : sc.getFQName()) 319 + "\n\tisIdentifier=" + isIdentifier 320 + "\n\tisInGenClass=" + isInGenClass 321 ); 322 } 323 if (!isInGenClass) { 324 Class clazz; 325 if (isIdentifier) { 326 clazz = (Class ) nd.getParent(); 328 if (nd.isFieldName()) { 329 PrimitiveElement pe = (PrimitiveElement) 330 clazz.getTypedElement(nd.getFieldName()); 331 if (pe == null) { 332 throw new SpeedoException("impossible to map the fields of the namedef of the metaobject '" + JormPathHelper.getPath(clazz) + "'."); 333 } 334 createFieldMapping(pe, null, cm); 335 } else { 336 Iterator it = nd.getNameRef().getProjection().values().iterator(); 337 while(it.hasNext()) { 338 PrimitiveElement pe = (PrimitiveElement) 339 clazz.getTypedElement((String ) it.next()); 340 if (pe == null) { 341 throw new SpeedoException("impossible to map the fields of the namedef of the metaobject '" + JormPathHelper.getPath(clazz) + "'."); 342 } 343 createFieldMapping(pe, null, cm); 344 } 345 } 346 } else { 347 MetaObject mo = nd.getParent(); 348 if (mo instanceof GenClassRef) { 349 NameDef classNd = (NameDef) cm.getIdentifierMapping().getLinkedMO(); 350 if ((nd.isFieldName() && classNd.isFieldName() && nd.getFieldName().equals(classNd.getFieldName())) 351 || (nd.isNameRef() && classNd.isNameRef() 352 && classNd.getNameRef().getCompositeName().equals(nd.getNameRef().getCompositeName()) 353 && classNd.getNameRef().getProjection().equals(nd.getNameRef().getProjection())) ) { 354 logger.log(BasicLevel.DEBUG, "Mapping of the GCR ref '" 358 + ((GenClassRef) mo).getName() 359 + "' already defined"); 360 } else { 361 createGenClassRefNameDef(sc, (GenClassRef) mo, cm, nd); 365 } 366 } else { 367 createClassRefNameDef(sc, (ClassRef) mo, cm, nd); 369 } 370 } 371 } else { 372 if (isIdentifier) { 373 creaGenClassRefIdNameDef(nd, sc, (RdbGenClassMapping) cm); 374 } else { 375 creaGenClassRefRefNameDef(nd, sc, (RdbGenClassMapping) cm); 376 } 377 } 378 } 379 380 381 private void createGenClassRefNameDef(SpeedoClass sc, 384 GenClassRef gcr, 385 CommonClassMapping cm, 386 NameDef gcrnd) 387 throws SpeedoException, PException { 388 logger.log(BasicLevel.DEBUG, "Defining the mapping of the GCR ref '" 389 + gcr.getName() + "' ..."); 390 RdbClassMultiMapping rcm = (RdbClassMultiMapping) cm; 392 if (gcrnd.isFieldName()) { 393 String fn = gcrnd.getFieldName(); 394 PrimitiveElement pe = (PrimitiveElement) 395 sc.jormclass.getTypedElement(fn); 396 if (pe == null) { 397 pe = sc.jormclass.getHiddenField(fn); 398 } 399 if (pe == null) { 400 throw new SpeedoException("No field '" + fn 401 + "' found on the class '" + sc.getFQName() + "'"); 402 } 403 logger.log(BasicLevel.DEBUG, "Map the PE '" + pe.getName() 404 + "' on the column '" + pe.getName() + "'."); 405 rcm.getRdbTable().createPrimitiveElementMapping(pe, pe.getName()); 406 } else if (gcrnd.isNameRef()) { 407 Iterator itClaFns = gcrnd.getNameRef().getProjection().values().iterator(); 408 while(itClaFns.hasNext()) { 409 String fn = (String ) itClaFns.next(); 410 PrimitiveElement pe = (PrimitiveElement) 411 sc.jormclass.getTypedElement(fn); 412 if (pe == null) { 413 pe = sc.jormclass.getHiddenField(fn); 414 } 415 if (pe == null) { 416 throw new SpeedoException("No field '" + fn 417 + "' found on the class '" + sc.getFQName() + "'"); 418 } 419 logger.log(BasicLevel.DEBUG, "Map the PE '" + pe.getName() 420 + "' on the column '" + pe.getName() + "'."); 421 rcm.getRdbTable().createPrimitiveElementMapping(pe, pe.getName()); 422 } 423 } 424 } 425 426 436 private void createClassRefNameDef(SpeedoClass sc, 437 ClassRef cr, 438 CommonClassMapping cm, 439 NameDef crnd) 440 throws SpeedoException, PException { 441 logger.log(BasicLevel.DEBUG, "Create the name def of the ClassRef: " 442 + JormPathHelper.getPath(cr)); 443 RdbClassMultiMapping rcm = (RdbClassMultiMapping) cm; 445 SpeedoClass tsc = sc.jdoPackage.jdoXMLDescriptor 447 .getSpeedoClass(cr.getMOClass().getFQName(), true); 448 RdbClassMultiMapping trcm = (RdbClassMultiMapping) 450 tsc.jormclass.getClassProject(cm.getProjectName()) 451 .getMapping(cm.getMapperName()).getClassMapping(); 452 SpeedoField sf = (SpeedoField) sc.jdoField.get(cr.getName()); 454 if (sf == null) { 455 throw new SpeedoException("impossible to map the namedef of the field '" 456 + JormPathHelper.getPath(cr) + "': no SpeedoField '" 457 + cr.getName()+ "' on the SpeedoClass " + sc.getFQName()); 458 } 459 460 NameDef tclassnd = (NameDef) 462 trcm.getIdentifierMapping().getLinkedMO(); 463 464 SpeedoExtension se = sf.getExtension(VENDOR_NAME, SOURCE_FK); 465 String sfk = (se == null ? null : se.value); 466 if (sfk != null) { 467 if (tsc.superClassName != null) { 469 throw new PException( 470 "Jorm does not support to store a polymorphic reference '" 471 + sc.getFQName() + "." + cr.getName()+ "'with a " + SOURCE_FK); 472 } 473 se = tsc.getExtensionByKey(SQL_NAME); 474 String tn = (se == null ? getTableName(sc) : se.value); 475 logger.log(BasicLevel.DEBUG, " - External table: " + tn); 476 RdbExternalTable exttable = rcm.createRdbExternalTable(tn); 477 if (sf.getExtensionByKey(REVERSE_FIELD) != null) { 478 exttable.setReadOnly(true); 479 } 480 exttable.setColocated(true); 483 trcm.getRdbTable().setColocated(true); 484 trcm.getRdbTable().setColocatedMaster(true); 485 trcm.addDependency(sc.getFQName()); 486 cm.addDependency(tsc.getFQName()); 487 488 se = sf.getExtension(VENDOR_NAME, REVERSE_FIELD); 491 logger.log(BasicLevel.DEBUG, " - readonly: " + (se != null)); 492 exttable.setReadOnly(se != null); 493 494 RdbJoin j = exttable.createRdbJoin(cr.getName()); 496 Iterator it = getPk2Fk(sfk).entrySet().iterator(); 497 while(it.hasNext()) { 498 Map.Entry me = (Map.Entry) it.next(); 499 logger.log(BasicLevel.DEBUG, " - join: " 500 + me.getKey() + " == " + me.getValue()); 501 j.addJoinColumnNames((String ) me.getKey(), 502 (String ) me.getValue()); 503 } 504 if (tclassnd.isFieldName()) { 506 RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping) 507 trcm.getPrimitiveElementMapping(tclassnd.getFieldName(), true); 508 PrimitiveElement pe = (PrimitiveElement) 509 sc.jormclass.getTypedElement(crnd.getFieldName()); 510 exttable.createPrimitiveElementMapping(pe, pem.getName(), null, false, j); 511 } else { 512 Map tclassndproj = tclassnd.getNameRef().getProjection(); 513 it = crnd.getNameRef().getProjection().entrySet().iterator(); 514 while(it.hasNext()) { 515 Map.Entry me = (Map.Entry) it.next(); 516 PrimitiveElement pe = (PrimitiveElement) 517 sc.jormclass.getTypedElement((String ) me.getValue()); 518 RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping) 519 trcm.getPrimitiveElementMapping( 520 (String ) tclassndproj.get(me.getKey()), true); 521 exttable.createPrimitiveElementMapping(pe, pem.getName(), null, false, j); 522 } 523 } 524 } else { 525 RdbTable table = rcm.getRdbTable(); 527 logger.log(BasicLevel.DEBUG, " - main table: " + table.getName()); 528 529 se = sf.getExtension(VENDOR_NAME, TARGET_FK); 530 String tfk = (se == null ? null : se.value); 531 Map pk2fk = null; 532 if (tfk != null) { 533 pk2fk = getPk2Fk(tfk); 534 } else { 535 logger.log(BasicLevel.DEBUG, " - default mapping"); 538 pk2fk = new HashMap (); 539 if (crnd.isFieldName()) { 540 RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping) 541 trcm.getPrimitiveElementMapping(tclassnd.getFieldName(), true); 542 pk2fk.put(pem.getName(), crnd.getFieldName()); 543 logger.log(BasicLevel.DEBUG, " - pk2fk: " + pem.getName() + " == " + crnd.getFieldName()); 544 } else { 545 Iterator it = crnd.getNameRef().getProjection().entrySet().iterator(); 546 Map tclassndproj = tclassnd.getNameRef().getProjection(); 547 while (it.hasNext()) { 548 Map.Entry me = (Map.Entry) it.next(); 549 RdbPrimitiveElementMapping pem = getPEMOfField( 550 tsc, cm.getProjectName(), cm.getMapperName(), (String ) 551 tclassndproj.get(me.getKey())); 552 pk2fk.put(pem.getName(), me.getValue()); 553 } 554 } 555 } 556 if (crnd.isFieldName()) { 558 RdbPrimitiveElementMapping pem = getPEMOfField( 560 tsc, cm.getProjectName(), cm.getMapperName(), tclassnd.getFieldName()); 561 562 PrimitiveElement pe = (PrimitiveElement) 564 sc.jormclass.getTypedElement(crnd.getFieldName()); 565 String colname = (String ) pk2fk.get(pem.getName()); 567 PrimitiveElementMapping pem2 = 569 table.getPrimitiveElementMappingByCol(colname); 570 if (pem2 == null) { 571 if (colname == null) { 573 throw new SpeedoException("No column name defined for a foreign key: " 574 + "\n\tfield name=" + pe.getName() 575 + "\n\tpk column name=" + pem.getName()); 576 } 577 table.createPrimitiveElementMapping(pe, colname, pem.getType(), false); 578 } else { 579 logger.log(BasicLevel.INFO, "pas collection:\n pe.getParent():" + pe.getParent().toString() 582 + "\n pe.getName():" + pe.getName() + "\n pem2.getLinkedMO():" + pem2.getLinkedMO()); 583 ((Class ) pe.getParent()).removeTypedElement(pe.getName()); 584 pe = (PrimitiveElement) pem2.getLinkedMO(); 585 crnd.setFieldName(pe.getName()); 586 } 587 } else { 588 Map tclassndproj = tclassnd.getNameRef().getProjection(); 589 Iterator it = crnd.getNameRef().getProjection().entrySet().iterator(); 590 while(it.hasNext()) { 591 Map.Entry me = (Map.Entry) it.next(); 592 PrimitiveElement pe = (PrimitiveElement) 594 sc.jormclass.getTypedElement((String ) me.getValue()); 595 RdbPrimitiveElementMapping pem = getPEMOfField( 597 tsc, cm.getProjectName(), cm.getMapperName(), 598 (String ) tclassndproj.get(me.getKey())); 599 String  |