1 23 24 package org.objectweb.jorm.generator.lib; 25 26 import org.apache.velocity.VelocityContext; 27 import org.apache.velocity.context.Context; 28 import org.objectweb.jorm.api.PException; 29 import org.objectweb.jorm.api.PMapper; 30 import org.objectweb.jorm.compiler.api.JormCompilerConfigurator; 31 import org.objectweb.jorm.compiler.api.JormCompilerParameter; 32 import org.objectweb.jorm.compiler.api.PExceptionCompiler; 33 import org.objectweb.jorm.generator.api.MOP; 34 import org.objectweb.jorm.metainfo.api.Class; 35 import org.objectweb.jorm.metainfo.api.ClassMapping; 36 import org.objectweb.jorm.metainfo.api.ClassProject; 37 import org.objectweb.jorm.metainfo.api.GenClass; 38 import org.objectweb.jorm.metainfo.api.GenClassRef; 39 import org.objectweb.jorm.metainfo.api.Mapping; 40 import org.objectweb.jorm.metainfo.api.NameDef; 41 import org.objectweb.jorm.metainfo.api.Package; 42 import org.objectweb.jorm.metainfo.api.ParentClassMapping; 43 import org.objectweb.jorm.metainfo.api.PrimitiveElementMapping; 44 import org.objectweb.jorm.metainfo.api.ReferenceMapping; 45 import org.objectweb.jorm.metainfo.api.TypedElement; 46 import org.objectweb.jorm.type.api.PExceptionTyping; 47 import org.objectweb.jorm.type.api.PType; 48 import org.objectweb.jorm.type.api.PTypeSpace; 49 import org.objectweb.jorm.util.api.Loggable; 50 import org.objectweb.jorm.util.io.api.TargetHolder; 51 import org.objectweb.medor.expression.api.Expression; 52 import org.objectweb.medor.expression.api.ExpressionException; 53 import org.objectweb.util.monolog.api.BasicLevel; 54 55 import java.io.File ; 56 import java.io.FileWriter ; 57 import java.io.IOException ; 58 import java.util.ArrayList ; 59 import java.util.Collection ; 60 import java.util.HashMap ; 61 import java.util.HashSet ; 62 import java.util.Iterator ; 63 import java.util.List ; 64 import java.util.Set ; 65 66 99 public class MappingGenerator extends CommonGenerator { 100 105 protected HashMap mmops = new HashMap (); 106 107 110 public MappingGenerator(JormCompilerConfigurator jcc, JormCompilerParameter cp) throws PException { 111 super(); 112 Iterator it = jcc.knownMappers(); 113 while (it.hasNext()) { 114 String mn = (String ) it.next(); 115 mmops.put(mn, jcc.getMOPFactory(mn).createMappingMOP(cp, mn)); 116 } 117 } 118 119 public String [][] getTemplateLibraries() { 120 String [][] res = new String [mmops.size()][]; 121 Iterator it = mmops.values().iterator(); 122 int i = 0; 123 while (it.hasNext()) { 124 res[i] = ((MOP) it.next()).getTemplateLibraries(); 125 i++; 126 } 127 return res; 128 } 129 130 139 public void generate(Class clazz, 140 TargetHolder holder, 141 JormCompilerParameter cp, 142 JormCompilerConfigurator jcc) throws PException { 143 concreteGenerate(clazz, holder, cp); 144 } 145 146 153 private void concreteGenerate(Class clazz, 154 TargetHolder holder, 155 JormCompilerParameter cp) throws PException { 156 157 ClassProject cpr = null; 159 Iterator it = clazz.getClassProjects().iterator(); 160 while (it.hasNext()) { 161 ClassProject tmpCp = (ClassProject) it.next(); 162 if (tmpCp.getProjectName().equals(cp.getProjectName())) { 163 cpr = tmpCp; 164 break; 165 } 166 } 167 if (cpr == null) { 168 throw new PExceptionCompiler("Cannot find the relevant project!"); 169 } 170 171 it = cpr.getMappings().iterator(); 173 while (it.hasNext()) { 174 Mapping mo = (Mapping) it.next(); 175 concreteGenerateWithMapper(mo.getMapperName(), clazz, holder, cp, mo); 176 } 177 } 178 179 189 190 private void concreteGenerateWithMapper(String mn, Class co, 191 TargetHolder holder, 192 JormCompilerParameter cp, 193 Mapping mo) throws PException { 194 String pack = ((Package ) co.getParent()).getName(); 195 String packroot = pack; 196 if (cp.isGeneratedWithMapperPackage()) { 197 pack = ("".equals(pack) ? mn : pack + "." + mn); 198 } 199 String fileName = co.getName() + PMapper.PCLASSMAPPINGAPPENDER; 201 if (pack.length() > 0) { 202 fileName = (pack + '.').replace('.', File.separatorChar) + fileName; 203 } 204 logger.log(BasicLevel.DEBUG, "Generate the " + fileName + " class"); 205 MOP mmop = (MOP) mmops.get(mo.getMapperName()); 206 207 Context ctx = new VelocityContext(); 209 ctx.put("abstractClass", new Boolean (co.isAbstract())); 210 ctx.put("velocityengine", velocityEngine); 211 ctx.put("holder", holder); 212 ctx.put("class", co); 213 ctx.put("mapping", mo); 214 ctx.put("dependencies", mo.getClassMapping().getDependencies()); 215 if (pack.length() > 0) { 216 ctx.put("package", pack); 217 ctx.put("packageroot", packroot); 218 } 219 ctx.put("mappername", mn); 220 ctx.put("noBindingCreation", new Boolean (cp.isBindingAbstract())); 221 ctx.put("cparam", cp); 222 CommonHelper ch = new CommonHelper(); 223 ch.setLogger(logger); 224 ctx.put("containsCharArrayField", new Boolean (ch.containsCharArrayField(mo))); 225 ctx.put("tools", ch); 226 ctx.put("header", GEN_TEMPLATE_DIR + "Header.vm"); 227 ctx.put("mappingTools", this); 228 ctx.put("bindingTools", this); 229 ((Loggable) mmop).setLogger(logger); 230 231 List pems = mo.getClassMapping().getAllPrimitiveElementMappings(); 232 ctx.put("pemlist", 233 pems.toArray(new PrimitiveElementMapping[pems.size()])); 234 235 mmop.initContext(ctx, co, cp.getProjectName(), mn); 236 237 ctx.put("useNamingKey", Boolean.FALSE); 238 NameDef nd = mo.getClassMapping().getIdentifierMapping().getNameDef(); 239 Class ancestorClass = getAncestor(co); 240 Expression namingfilter; 241 try { 242 namingfilter = ancestorClass.getInheritanceFilter(nd); 243 } catch (ExpressionException e) { 244 throw new PException(e); 245 } 246 Object namingKey = co.getInheritanceNamingKey(nd); 247 if (namingfilter != null && namingKey !=null) { 248 ctx.put("useNamingKey", Boolean.TRUE); 249 PType namingKeyType = namingfilter.getType(); 251 ctx.put("namingKeyTypeStr", ptype2String(namingKeyType)); 252 String namingKeyStr = null;; 253 switch(namingKeyType.getTypeCode()) { 254 case PType.TYPECODE_BOOLEAN: 255 if (namingKey instanceof Boolean ) { 256 namingKeyStr = namingKey.toString(); 257 } 258 break; 259 case PType.TYPECODE_OBJBOOLEAN: 260 if (namingKey instanceof Boolean ) { 261 namingKeyStr = (((Boolean ) namingKey).booleanValue() 262 ? "Boolean.TRUE" : "Boolean.FALSE"); 263 } 264 break; 265 case PType.TYPECODE_BYTE: 266 case PType.TYPECODE_SHORT: 267 case PType.TYPECODE_INT: 268 case PType.TYPECODE_LONG: 269 PType jlpt = getJavaLangPrimitive(namingKeyType); 270 if (namingKey instanceof String ) { 271 namingKeyStr = jlpt.getJavaName() + ".valueOf" 272 +"(\"" + namingKey.toString() + "\")"; 273 } else { 274 namingKeyStr = "new " + jlpt.getJavaName() 275 + "((" + namingKeyType.getJavaName() 276 + ") " + namingKey.toString() + ")"; 277 } 278 break; 279 case PType.TYPECODE_OBJBYTE: 280 case PType.TYPECODE_OBJSHORT: 281 case PType.TYPECODE_OBJINT: 282 case PType.TYPECODE_OBJLONG: 283 if (namingKey instanceof String ) { 284 namingKeyStr = "new " + namingKeyType.getJavaName() 285 + "(\"" + namingKey.toString() + "\")"; 286 } else { 287 namingKeyStr = "new " + namingKeyType.getJavaName() 288 + "((" + getPrimitive(namingKeyType).getJavaName() 289 + ") " + namingKey.toString() + ")"; 290 } 291 break; 292 case PType.TYPECODE_STRING: 293 namingKeyStr = "\"" + namingKey.toString() + "\""; 294 break; 295 } 296 297 if (namingKey == null) { 298 throw new PExceptionTyping("Naming key value no corresponding to the type of the filter: " 299 + "filter type: " + namingKeyType.getJavaName() 300 + " / naming key value: " + namingKey); 301 } 302 ctx.put("namingKey", namingKeyStr); 303 } 304 305 ArrayList gcms = new ArrayList (); 306 getGenClassMapping(mo, cp.getProjectName(), gcms); 307 ctx.put("gcms", gcms); 308 309 List crms = getClassReferenceMapping(mo, cp.getProjectName()); 310 ctx.put("crms", crms); 311 312 try { 313 FileWriter fw = holder.getFileWriter(fileName + ".java"); 314 if (template == null) { 315 template = velocityEngine.getTemplate(GEN_TEMPLATE_DIR + "Mapping.vm"); 316 } 317 template.merge(ctx, fw); 318 fw.flush(); 319 fw.close(); 320 } catch (Exception e) { 321 throw new PExceptionCompiler(e, "Problem while writing Mapping java file: " + fileName + ".java"); 322 } 323 } 324 325 326 333 private void abstractGenerate(Class clazz, 334 TargetHolder holder, 335 JormCompilerParameter cp) throws PException { 336 HashSet mapperNames = new HashSet (); 337 getMapperNames(clazz, cp.getProjectName(), mapperNames); 338 for (Iterator itMapperName = mapperNames.iterator(); itMapperName.hasNext();) { 339 String mapperName = (String ) itMapperName.next(); 340 Collection nds = clazz.getNameDefs(); 341 Class classWithNd = clazz; 342 while(nds.size() < 1 && classWithNd.getInheritedClassNumber() > 0) { 343 classWithNd = (Class ) classWithNd.getSuperClasses().iterator().next(); 345 nds = classWithNd.getNameDefs(); 346 } 347 if (nds.size() < 1) { 348 logger.log(BasicLevel.WARN, "AbstractClass: No NameDef defined for the class " + clazz.getFQName()); 349 return; 350 } 351 if (nds.size() == 1) { 352 abstractGenerateWithNameDef(mapperName, clazz, holder, cp, null); 353 } else { 354 Iterator it = nds.iterator(); 355 while(it.hasNext()) { 356 NameDef nd = (NameDef) it.next(); 357 abstractGenerateWithNameDef(mapperName, clazz, holder, cp, 358 (nd.getName() != null && nd.getName().length() == 0 359 ? null 360 : nd.getName())); 361 } 362 } 363 } 364 } 365 366 private void getMapperNames(Class clazz, String projectName, Set res) { 367 if (clazz.isAbstract()) { 368 for (Iterator itClass = clazz.getSubClasses().iterator(); itClass.hasNext();) { 369 Class subClass = (Class ) itClass.next(); 370 getMapperNames(subClass, projectName, res); 371 } 372 } else { 373 res.addAll(clazz.getClassProject(projectName).getMappers()); 374 } 375 } 376 377 private void abstractGenerateWithNameDef(String mapperName, 378 Class clazz, 379 TargetHolder holder, 380 JormCompilerParameter cp, 381 String ndName) throws PException { 382 String packName = ((Package ) clazz.getParent()).getName(); 383 if (cp.isGeneratedWithMapperPackage()) { 384 packName = ("".equals(packName) ? mapperName : packName + "." + mapperName); 385 } 386 387 String fileName = clazz.getName() + PMapper.PCLASSMAPPINGAPPENDER; 389 if (ndName != null) { 390 if (packName != null && packName.length() > 0) { 391 packName += "." + ndName; 392 } else { 393 packName = ndName; 394 } 395 } 396 if (packName.length() > 0) { 397 fileName = (packName + '.').replace('.', File.separatorChar) + fileName; 398 } 399 logger.log(BasicLevel.DEBUG, "Generate the " + fileName + " class"); 400 MOP mmop = (MOP) mmops.get(mapperName); 401 Context ctx = new VelocityContext(); 402 ctx.put("class", clazz); 403 if (packName.length() > 0) { 404 ctx.put("package", packName); 405 } 406 ctx.put("cparam", cp); 407 CommonHelper ch = new CommonHelper(); 408 ch.setLogger(logger); 409 ctx.put("tools", ch); 410 ctx.put("mappername", mapperName); 411 ctx.put("noBindingCreation", Boolean.TRUE); 412 ctx.put("abstractClass", Boolean.TRUE); 413 ctx.put("header", GEN_TEMPLATE_DIR + "Header.vm"); 414 ctx.put("mappingTools", this); 415 ClassProject classproject = clazz.getClassProject(cp.getProjectName()); 416 ArrayList dependencies = new ArrayList (); 417 List pems = null; 418 if (classproject != null) { 419 Collection ms = classproject.getMappings(); 420 if (!ms.isEmpty()) { 421 Iterator it = ms.iterator(); 422 while(it.hasNext()) { 423 Mapping m = (Mapping) it.next(); 424 pems = m.getClassMapping().getAllPrimitiveElementMappings(); 425 ClassMapping cm = m.getClassMapping(); 426 if (cm != null) { 427 dependencies.addAll(cm.getDependencies()); 428 } 429 } 430 } 431 } 432 if (pems != null) { 433 ctx.put("pemlist", 434 pems.toArray(new PrimitiveElementMapping[pems.size()])); 435 } 436 ((Loggable) mmop).setLogger(logger); 437 mmop.initContext(ctx, clazz, cp.getProjectName(), mapperName); 438 ctx.put("dependencies", dependencies); 439 FileWriter fw = null; 440 try { 441 fw = holder.getFileWriter(fileName + ".java"); 443 velocityEngine.getTemplate(GEN_TEMPLATE_DIR + "Mapping.vm").merge(ctx, fw); 444 } catch (Exception e) { 445 throw new PExceptionCompiler(e, "Problem while writing Mapping java file: " + fileName + ".java"); 446 } finally { 447 try { 448 if (fw != null) { 449 fw.flush(); 450 fw.close(); 451 } 452 } catch (IOException e1) { 453 e1.printStackTrace(); 454 } 455 } 456 457 } 458 459 private void getGenClassMapping(Mapping mo, String projname, ArrayList gcms) { 460 gcms.addAll(mo.getGenClassMappings()); 461 for(Iterator it = mo.getClassMapping().getParentClassMappings().iterator(); 462 it.hasNext();) { 463 getGenClassMapping(((ParentClassMapping) it.next()).getMOClass() 464 .getClassProject(projname) 465 .getMapping(mo.getMapperName()), 466 projname, 467 gcms); 468 } 469 } 470 471 private List getClassReferenceMapping(Mapping mapping, String projname) { 472 HashMap ref2refmap = new HashMap (); 473 ArrayList ms = new ArrayList (); 474 ms.add(mapping); 475 while(!ms.isEmpty()) { 476 Mapping mo = (Mapping) ms.remove(0); 478 for(Iterator it = mo.getClassMapping().getReferenceMappings().iterator();it.hasNext();) { 481 ReferenceMapping rm = (ReferenceMapping) it.next(); 482 Object old = ref2refmap.put(rm.getLinkedMO(), rm); 483 if (old != null) { 484 ref2refmap.put(rm.getLinkedMO(), old); 486 } 487 } 488 for(Iterator it = mo.getClassMapping().getParentClassMappings().iterator(); 489 it.hasNext();) { 490 ms.add(((ParentClassMapping) it.next()).getMOClass() 491 .getClassProject(projname) 492 .getMapping(mo.getMapperName())); 493 } 494 } 495 return new ArrayList (ref2refmap.values()); 496 } 497 498 private Class getAncestor(Class clazz) throws PException { 499 Collection superClasses = clazz.getSuperClasses(); 500 if (superClasses.isEmpty()) { 501 return clazz; 502 } 503 if (superClasses.size() == 1) { 504 return getAncestor((Class ) superClasses.iterator().next()); 505 } 506 throw new PException("Multiple inheritance not supported in the current implementation"); 507 } 508 509 512 public String getOwner(TypedElement te, Class owner, String ownerName) { 513 return (te.getParent() == owner 514 ? ownerName 515 : "\"" + ((Class ) te.getParent()).getFQName() + "\""); 516 } 517 518 522 public String ptype2CTString(PType pt) throws PExceptionTyping { 523 if (pt == null) { 524 throw new PExceptionTyping("null parameter forbidden"); 525 } 526 switch (pt.getTypeCode()) { 527 case PType.TYPECODE_CHAR: 528 return "PNamingContext.CTCHAR"; 529 case PType.TYPECODE_OBJCHAR: 530 return "PNamingContext.CTOCHAR"; 531 case PType.TYPECODE_BYTE: 532 return "PNamingContext.CTBYTE"; 533 case PType.TYPECODE_OBJBYTE: 534 return "PNamingContext.CTOBYTE"; 535 case PType.TYPECODE_SHORT: 536 return "PNamingContext.CTSHORT"; 537 case PType.TYPECODE_OBJSHORT: 538 return "PNamingContext.CTOSHORT"; 539 case PType.TYPECODE_INT: 540 return "PNamingContext.CTINT"; 541 case PType.TYPECODE_OBJINT: 542 return "PNamingContext.CTOINT"; 543 case PType.TYPECODE_LONG: 544 return "PNamingContext.CTLONG"; 545 case PType.TYPECODE_OBJLONG: 546 return "PNamingContext.CTOLONG"; 547 case PType.TYPECODE_STRING: 548 return "PNamingContext.CTSTRING"; 549 case PType.TYPECODE_DATE: 550 return "PNamingContext.CTDATE"; 551 case PType.TYPECODE_CHARARRAY: 552 return "PNamingContext.CTCHARARRAY"; 553 case PType.TYPECODE_BYTEARRAY: 554 return "PNamingContext.CTBYTEARRAY"; 555 default: 556 throw new PExceptionTyping("The following " + pt.getJormName() 557 + " type has'nt been allowed to be used as a PName field"); 558 } 559 560 } 561 562 public PType getJavaLangPrimitive(PType pt) { 563 switch (pt.getTypeCode()) { 564 case PType.TYPECODE_BOOLEAN: 565 case PType.TYPECODE_OBJBOOLEAN: 566 return PTypeSpace.OBJBOOLEAN; 567 case PType.TYPECODE_CHAR: 568 case PType.TYPECODE_OBJCHAR: 569 return PTypeSpace.OBJCHAR; 570 case PType.TYPECODE_BYTE: 571 case PType.TYPECODE_OBJBYTE: 572 return PTypeSpace.OBJBYTE; 573 case PType.TYPECODE_SHORT: 574 case PType.TYPECODE_OBJSHORT: 575 return PTypeSpace.OBJSHORT; 576 case PType.TYPECODE_INT: 577 case PType.TYPECODE_OBJINT: 578 return PTypeSpace.OBJINT; 579 case PType.TYPECODE_LONG: 580 case PType.TYPECODE_OBJLONG: 581 return PTypeSpace.OBJLONG; 582 default: 583 return null; 584 } 585 } 586 587 public PType getPrimitive(PType pt) { 588 switch (pt.getTypeCode()) { 589 case PType.TYPECODE_BOOLEAN: 590 case PType.TYPECODE_OBJBOOLEAN: 591 return PTypeSpace.BOOLEAN; 592 case PType.TYPECODE_CHAR: 593 case PType.TYPECODE_OBJCHAR: 594 return PTypeSpace.CHAR; 595 case PType.TYPECODE_BYTE: 596 case PType.TYPECODE_OBJBYTE: 597 return PTypeSpace.BYTE; 598 case PType.TYPECODE_SHORT: 599 case PType.TYPECODE_OBJSHORT: 600 return PTypeSpace.SHORT; 601 case PType.TYPECODE_INT: 602 case PType.TYPECODE_OBJINT: 603 return PTypeSpace.INT; 604 case PType.TYPECODE_LONG: 605 case PType.TYPECODE_OBJLONG: 606 return PTypeSpace.LONG; 607 default: 608 return null; 609 } 610 } 611 612 616 public String ptype2String(PType pt) throws PExceptionTyping { 617 if (pt == null) { 618 throw new PExceptionTyping("null parameter forbidden"); 619 } 620 return pt.getProgName(); 621 } 622 623 629 public String getGenclass(int level) { 630 String res = ""; 631 for (int i = 0; i < level; i++) { 632 res += ".getGenClassMapping()"; 633 } 634 return res; 635 } 636 637 641 public int getIndexNumber(GenClass gc) { 642 Iterator it = gc.iterateIndexField(); 643 int res = 0; 644 while (it.hasNext()) { 645 res++; 646 it.next(); 647 } 648 return res; 649 } 650 651 public TypedElement getLastElement(GenClassRef gcr) { 652 TypedElement o = gcr; 653 while (o instanceof GenClassRef) { 654 GenClassRef g = ((GenClassRef) o); 655 if (g.isClassRef()) 656 o = g.getClassRef(); 657 else if (g.isGenClassRef()) 658 o = g.getClassRef(); 659 else if (g.isPrimitive()) 660 o = g.getPrimitiveElement(); 661 } 662 return o; 663 } 664 665 public ArrayList getGenClassNames(GenClassRef gcr) { 666 ArrayList gcns = new ArrayList (5); 667 TypedElement o = gcr; 668 while (o instanceof GenClassRef) { 669 GenClassRef g = ((GenClassRef) o); 670 gcns.add(g.getGenClassName()); 671 if (g.isClassRef()) 672 o = g.getClassRef(); 673 else if (g.isGenClassRef()) 674 o = g.getGenClassRef(); 675 else if (g.isPrimitive()) 676 o = g.getPrimitiveElement(); 677 } 678 ArrayList res = new ArrayList (gcns.size()); 679 for (int i = 0; i < gcns.size(); i++) { 680 String s = "new String[]{"; 681 for (int j = 0; j <= i; j++) { 682 String elem = "\"" + gcns.get(j) + "\""; 683 s += elem + (i == j ? "}" : ","); 684 } 685 res.add(s); 686 } 687 return res; 688 } 689 } 690 | Popular Tags |