1 28 29 package com.caucho.amber.field; 30 31 import com.caucho.amber.AmberRuntimeException; 32 import com.caucho.amber.expr.AmberExpr; 33 import com.caucho.amber.expr.ManyToOneExpr; 34 import com.caucho.amber.expr.PathExpr; 35 import com.caucho.amber.query.QueryParser; 36 import com.caucho.amber.table.Column; 37 import com.caucho.amber.table.ForeignColumn; 38 import com.caucho.amber.table.LinkColumns; 39 import com.caucho.amber.table.Table; 40 import com.caucho.amber.type.RelatedType; 41 import com.caucho.amber.type.Type; 42 import com.caucho.config.ConfigException; 43 import com.caucho.java.JavaWriter; 44 import com.caucho.log.Log; 45 import com.caucho.util.CharBuffer; 46 import com.caucho.util.L10N; 47 48 import javax.persistence.CascadeType; 49 import java.io.IOException ; 50 import java.util.ArrayList ; 51 import java.util.HashSet ; 52 import java.util.logging.Logger ; 53 54 57 public class EntityManyToOneField extends CascadableField { 58 private static final L10N L = new L10N(EntityManyToOneField.class); 59 private static final Logger log = Log.open(EntityManyToOneField.class); 60 61 private LinkColumns _linkColumns; 62 63 private RelatedType _targetType; 64 65 private int _targetLoadIndex; 66 67 private DependentEntityOneToOneField _targetField; 68 private PropertyField _aliasField; 69 70 private boolean _isInsert = true; 71 private boolean _isUpdate = true; 72 73 private boolean _isSourceCascadeDelete; 74 private boolean _isTargetCascadeDelete; 75 76 public EntityManyToOneField(RelatedType relatedType, 77 String name, 78 CascadeType[] cascadeType) 79 throws ConfigException 80 { 81 super(relatedType, name, cascadeType); 82 } 83 84 public EntityManyToOneField(RelatedType relatedType, 85 String name) 86 throws ConfigException 87 { 88 this(relatedType, name, null); 89 } 90 91 public EntityManyToOneField(RelatedType relatedType) 92 { 93 super(relatedType); 94 } 95 96 99 public void setType(Type targetType) 100 { 101 if (! (targetType instanceof RelatedType)) 102 throw new AmberRuntimeException(L.l("many-to-one requires an entity target at '{0}'", 103 targetType)); 104 105 _targetType = (RelatedType) targetType; 106 } 107 108 112 public RelatedType getEntitySourceType() 113 { 114 return (RelatedType) getSourceType(); 115 } 116 117 121 public RelatedType getEntityTargetType() 122 { 123 return _targetType; 124 } 125 126 129 public String getForeignTypeName() 130 { 131 return getEntityTargetType().getForeignTypeName(); 133 } 134 135 138 public void setTargetCascadeDelete(boolean isCascadeDelete) 139 { 140 _isTargetCascadeDelete = isCascadeDelete; 141 } 142 143 146 public void setSourceCascadeDelete(boolean isCascadeDelete) 147 { 148 _isSourceCascadeDelete = isCascadeDelete; 149 } 150 151 154 public boolean isTargetCascadeDelete() 155 { 156 return _isTargetCascadeDelete; 157 } 158 159 162 public boolean isSourceCascadeDelete() 163 { 164 return _isSourceCascadeDelete; 165 } 166 167 170 public void setLinkColumns(LinkColumns linkColumns) 171 { 172 _linkColumns = linkColumns; 173 } 174 175 178 public LinkColumns getLinkColumns() 179 { 180 return _linkColumns; 181 } 182 183 186 public void setTargetField(DependentEntityOneToOneField field) 187 { 188 _targetField = field; 189 } 190 191 194 public void setAliasField(PropertyField alias) 195 { 196 _aliasField = alias; 197 } 198 199 202 public void init() 203 throws ConfigException 204 { 205 super.init(); 206 207 Id id = getEntityTargetType().getId(); 208 ArrayList <Column> keys = id.getColumns(); 209 210 if (_linkColumns == null) { 211 ArrayList <ForeignColumn> columns = new ArrayList <ForeignColumn>(); 212 213 for (int i = 0; i < keys.size(); i++) { 214 Column key = keys.get(i); 215 216 String name; 217 218 if (keys.size() == 1) 219 name = getName(); 220 else 221 name = getName() + "_" + key.getName(); 222 223 columns.add(getEntitySourceType().getTable().createForeignColumn(name, key)); 224 } 225 226 _linkColumns = new LinkColumns(getEntitySourceType().getTable(), 227 _targetType.getTable(), 228 columns); 229 } 230 231 if (getEntitySourceType().getId() != null) { 232 for (AmberField field : getEntitySourceType().getId().getKeys()) { 234 if (field instanceof PropertyField) { 235 PropertyField prop = (PropertyField) field; 236 237 for (ForeignColumn column : _linkColumns.getColumns()) { 238 if (prop.getColumn().getName().equals(column.getName())) 239 _aliasField = prop; 240 } 241 } 242 } 243 } 244 245 _targetLoadIndex = getEntitySourceType().getLoadGroupIndex(); 247 _linkColumns.setTargetCascadeDelete(isTargetCascadeDelete()); 248 _linkColumns.setSourceCascadeDelete(isSourceCascadeDelete()); 249 } 250 251 254 public void generatePostConstructor(JavaWriter out) 255 throws IOException 256 { 257 out.println(getSetterName() + "(" + generateSuperGetter() + ");"); 258 } 259 260 263 public AmberExpr createExpr(QueryParser parser, PathExpr parent) 264 { 265 return new ManyToOneExpr(parent, _linkColumns); 266 } 267 268 271 public ForeignColumn getColumn(Column targetColumn) 272 { 273 return _linkColumns.getSourceColumn(targetColumn); 274 } 275 276 279 public void generateInsertColumns(ArrayList <String > columns) 280 { 281 if (_isInsert && _aliasField == null) 282 _linkColumns.generateInsert(columns); 283 } 284 285 288 public String generateLoadSelect(Table table, String id) 289 { 290 if (_aliasField != null) 291 return null; 292 293 if (_linkColumns.getSourceTable() != table) 294 return null; 295 else 296 return _linkColumns.generateSelectSQL(id); 297 } 298 299 302 public String generateSelect(String id) 303 { 304 if (_aliasField != null) 305 return null; 306 307 return _linkColumns.generateSelectSQL(id); 308 } 309 310 313 public void generateUpdate(CharBuffer sql) 314 { 315 if (_aliasField != null) 316 return; 317 318 if (_isUpdate) { 319 sql.append(_linkColumns.generateUpdateSQL()); 320 } 321 } 322 323 326 public void generatePrologue(JavaWriter out, HashSet <Object > completedSet) 327 throws IOException 328 { 329 super.generatePrologue(out, completedSet); 330 331 out.println(); 332 333 Id id = getEntityTargetType().getId(); 334 335 out.println("protected transient " + id.getForeignTypeName() + " __caucho_field_" + getName() + ";"); 336 337 if (_aliasField == null) { 338 id.generatePrologue(out, completedSet, getName()); 339 } 340 } 341 342 345 public void generateJoin(CharBuffer cb, 346 String sourceTable, 347 String targetTable) 348 { 349 cb.append(_linkColumns.generateJoin(sourceTable, targetTable)); 350 } 351 352 355 public int generateLoad(JavaWriter out, String rs, 356 String indexVar, int index) 357 throws IOException 358 { 359 if (_aliasField != null) 360 return index; 361 362 out.print("__caucho_field_" + getName() + " = "); 363 364 index = getEntityTargetType().getId().generateLoadForeign(out, rs, 365 indexVar, index, 366 getName()); 367 368 out.println(";"); 369 370 378 379 382 int group = _targetLoadIndex / 64; 383 long mask = (1L << (_targetLoadIndex % 64)); 384 385 387 return index; 389 } 390 391 394 public int generateLoadEager(JavaWriter out, String rs, 395 String indexVar, int index) 396 throws IOException 397 { 398 if (! isLazy()) { 399 400 int group = _targetLoadIndex / 64; 401 long mask = (1L << (_targetLoadIndex % 64)); 402 String loadVar = "__caucho_loadMask_" + group; 403 404 407 String javaType = getJavaTypeName(); 408 409 out.println("if ((preloadedProperties == null) || (! preloadedProperties.containsKey(\"" + getName() + "\"))) {"); 410 out.pushDepth(); 411 412 String indexS = "_" + (_targetLoadIndex / 64); 413 indexS += "_" + (1L << (_targetLoadIndex % 64)); 414 415 generateLoadProperty(out, indexS, "aConn"); 416 417 out.popDepth(); 418 out.println("} else {"); 419 420 out.println(" " + generateSuperSetter("(" + javaType + ") preloadedProperties.get(\"" + getName() + "\")") + ";"); 421 out.println("}"); 422 } 423 424 return index; 425 } 426 427 430 public void generateGetProperty(JavaWriter out) 431 throws IOException 432 { 433 String javaType = getJavaTypeName(); 434 435 int group = _targetLoadIndex / 64; 436 long mask = (1L << (_targetLoadIndex % 64)); 437 String loadVar = "__caucho_loadMask_" + group; 438 439 out.println(); 440 out.println("public " + javaType + " __caucho_item_" + getGetterName() + "(com.caucho.amber.manager.AmberConnection aConn)"); 441 out.println("{"); 442 out.pushDepth(); 443 444 out.println("if (aConn != null) {"); 445 out.pushDepth(); 446 447 String index = "_" + (_targetLoadIndex / 64); 448 index += "_" + (1L << (_targetLoadIndex % 64)); 449 450 if (_aliasField == null) { 451 out.println("__caucho_load_" + getLoadGroupIndex() + "(aConn);"); 452 } 453 454 out.println(loadVar + " |= " + mask + "L;"); 455 456 generateLoadProperty(out, index, "aConn"); 457 458 out.println("return v"+index+";"); 459 460 out.popDepth(); 461 out.println("}"); 462 463 out.println("return null;"); 464 465 out.popDepth(); 466 out.println("}"); 467 468 out.println(); 469 out.println("public " + javaType + " " + getGetterName() + "()"); 470 out.println("{"); 471 out.pushDepth(); 472 473 out.println("if (__caucho_item != null) {"); 474 out.pushDepth(); 475 476 String extClassName = getEntitySourceType().getInstanceClassName(); out.println(extClassName + " item = (" + extClassName + ") __caucho_item.getEntity();"); 479 480 out.println("item.__caucho_item_" + getGetterName() + "(__caucho_session);"); 481 482 generateCopyLoadObject(out, "super", "item", getLoadGroupIndex()); 483 484 487 out.println("__caucho_loadMask_" + group + " |= item.__caucho_loadMask_" + group + " & " + mask + "L;"); 488 489 out.popDepth(); 490 out.println("}"); 491 492 out.println("else"); 493 out.pushDepth(); 494 out.print("if (__caucho_session != null && "); 495 out.println("(" + loadVar + " & " + mask + "L) == 0) {"); 496 out.pushDepth(); 497 498 out.println("return __caucho_item_" + getGetterName() + "(__caucho_session);"); 499 500 out.popDepth(); 501 out.println("}"); 502 out.popDepth(); 503 504 out.println(); 505 out.println("return " + generateSuperGetter() + ";"); 506 507 out.popDepth(); 508 out.println("}"); 509 } 510 511 514 public void generateLoadProperty(JavaWriter out, 515 String index, 516 String session) 517 throws IOException 518 { 519 String javaType = getJavaTypeName(); 520 521 if (_targetField != null) { 522 out.println("java.util.Map map_" + index + " = new java.util.HashMap();"); 523 out.println("map_" + index + ".put(\"" + _targetField.getName() + "\", this);"); 524 out.println(); 525 } 526 527 if (isAbstract()) { 529 String proxy = "aConn.loadProxy(\"" + getEntityTargetType().getName() + "\", __caucho_field_" + getName() + ")"; 530 531 proxy = getEntityTargetType().getProxyClass().getName() + " v" + index + " = (" + getEntityTargetType().getProxyClass().getName() + ") " + proxy + ";"; 532 533 out.println(proxy); 534 out.println(generateSuperSetter("v" + index) + ";"); 535 } 536 else { 537 String targetType = _targetType.getBeanClass().getName(); 538 out.print(targetType + " v"+index+" = (" + targetType + ") "+session+".find(" + targetType + ".class, "); 539 540 if (_aliasField == null) { 541 out.print("__caucho_field_" + getName()); 542 } 543 else { 544 out.print(_aliasField.generateGet("super")); 545 } 546 547 if (_targetField == null) 548 out.println(");"); 549 else 550 out.println(", map_" + index + ");"); 551 552 out.println(generateSuperSetter("v" + index) + ";"); 553 } 554 } 555 556 559 public void generateCopyUpdateObject(JavaWriter out, 560 String dst, String src, 561 int updateIndex) 562 throws IOException 563 { 564 567 String var = "__caucho_field_" + getName(); 569 out.println(generateAccessor(dst, var) + " = " + generateAccessor(src, var) + ";"); 570 571 String value = generateGet(src); 572 out.println(generateSet(dst, value) + ";"); 573 574 } 576 577 580 public void generateCopyLoadObject(JavaWriter out, 581 String dst, String src, 582 int updateIndex) 583 throws IOException 584 { 585 588 String var = "__caucho_field_" + getName(); 590 out.println(generateAccessor(dst, var) + " = " + generateAccessor(src, var) + ";"); 591 if (! dst.equals("super")) { out.println("((" + getEntitySourceType().getInstanceClassName() + ") " + dst + ")." + 594 generateSuperSetter(generateSuperGetter()) + ";"); 595 } 596 597 600 603 String value = generateGet(src); 604 out.println(generateSet(dst, value) + ";"); 605 606 608 615 } 616 617 private String generateAccessor(String src, String var) 618 { 619 if (src.equals("super")) 620 return var; 621 else 622 return "((" + getEntitySourceType().getInstanceClassName() + ") " + src + ")." + var; 623 } 624 625 628 public void generateSetProperty(JavaWriter out) 629 throws IOException 630 { 631 633 Id id = getEntityTargetType().getId(); 634 String var = "__caucho_field_" + getName(); 635 636 String keyType = getEntityTargetType().getId().getForeignTypeName(); 637 638 out.println(); 639 out.println("public void " + getSetterName() + "(" + getJavaTypeName() + " v)"); 640 out.println("{"); 641 out.pushDepth(); 642 643 int group = getLoadGroupIndex() / 64; 644 long loadMask = (1L << (getLoadGroupIndex() % 64)); 645 String loadVar = "__caucho_loadMask_" + group; 646 647 if (_aliasField == null) { 648 out.println("if ((" + loadVar + " & " + loadMask + "L) == 0 && __caucho_session != null) {"); 649 out.println(" __caucho_load_0(__caucho_session);"); 650 out.println("}"); 651 652 out.println(); 653 out.println("if (v == null) {"); 654 out.println(" if (" + var + " == null) {"); 655 out.println(" " + generateSuperSetter("null") + ";"); 656 out.println(" return;"); 657 out.println(" }"); 658 659 out.println(); 660 out.println(" " + var + " = null;"); 661 out.println("} else {"); 662 out.pushDepth(); 663 out.print(keyType + " key = "); 664 665 RelatedType targetType = getEntityTargetType(); 666 667 if (targetType.isEJBProxy(getJavaTypeName())) { 668 out.print(id.generateGetProxyKey("v")); 670 } 671 else { 672 String v = "((" + getEntityTargetType().getInstanceClassName()+ ") v)"; 673 674 out.print(id.toObject(id.generateGetProperty(v))); 675 } 676 677 out.println(";"); 678 679 out.println(); 680 out.println("if (key.equals(" + var + ")) {"); 681 out.println(" " + generateSuperSetter("v") + ";"); 682 out.println(" return;"); 683 out.println("}"); 684 685 out.println(); 686 out.println(var + " = key;"); 687 688 out.popDepth(); 689 out.println("}"); 690 691 out.println(); 692 693 out.println(generateSuperSetter("v") + ";"); 694 out.println(); 695 out.println("if (__caucho_session != null) {"); 696 out.pushDepth(); 697 698 String dirtyVar = "__caucho_dirtyMask_" + (getIndex() / 64); 699 long dirtyMask = (1L << (getIndex() % 64)); 700 701 out.println(dirtyVar + " |= " + dirtyMask + "L;"); 702 out.println(loadVar + " |= " + loadMask + "L;"); 703 out.println("__caucho_session.update(this);"); 704 705 out.println("__caucho_session.addCompletion(__caucho_home.createManyToOneCompletion(\"" + getName() + "\", this, v));"); 706 707 out.println(); 708 709 out.popDepth(); 710 out.println("}"); 711 } 712 else { 713 out.println("throw new IllegalStateException(\"aliased field cannot be set\");"); 714 } 715 716 out.popDepth(); 717 out.println("}"); 718 } 719 720 723 public boolean generateFlushCheck(JavaWriter out) 724 throws IOException 725 { 726 String getter = generateSuperGetter(); 727 728 out.println("if (" + getter + " != null) {"); 729 out.pushDepth(); 730 out.println("int state = ((com.caucho.amber.entity.Entity) " + getter + ").__caucho_getEntityState();"); 731 732 out.println("if (this.__caucho_state < com.caucho.amber.entity.Entity.P_DELETING"); 734 out.println(" && (state <= com.caucho.amber.entity.Entity.P_NEW || "); 735 out.println(" state >= com.caucho.amber.entity.Entity.P_DELETED))"); 736 737 String errorString = ("(\"amber flush: unable to flush " + 738 getEntitySourceType().getName() + "[\" + __caucho_getPrimaryKey() + \"] "+ 739 "with non-managed dependent relationship many-to-one to "+ 740 getEntityTargetType().getName() + "\")"); 741 742 out.println(" throw new IllegalStateException" + errorString + ";"); 743 out.popDepth(); 744 out.println("}"); 745 746 return true; 747 } 748 749 752 public void generateSet(JavaWriter out, String pstmt, 753 String index, String source) 754 throws IOException 755 { 756 if (_aliasField != null) 757 return; 758 759 if (source == null) { 760 throw new NullPointerException (); 761 } 762 763 String var = "__caucho_field_" + getName(); 764 765 if (! source.equals("this") && ! source.equals("super")) 766 var = source + "." + var; 767 768 if (! isAbstract()) { 769 out.println("if (" + var + " != null) {"); 771 } 772 else { 773 775 String amberVar = getFieldName(); 777 778 out.println("int " + amberVar + "_state = (" + var + " == null) ? "); 779 out.println("com.caucho.amber.entity.Entity.TRANSIENT : "); 780 out.println("((com.caucho.amber.entity.Entity) " + amberVar + ")."); 781 out.println("__caucho_getEntityState();"); 782 783 out.println("if (" + amberVar + "_state >= com.caucho.amber.entity.Entity.P_NEW &&"); 784 out.println(" " + amberVar + "_state <= com.caucho.amber.entity.Entity.P_TRANSACTIONAL) {"); 785 } 786 787 out.pushDepth(); 788 789 Id id = getEntityTargetType().getId(); 790 ArrayList <IdField> keys = id.getKeys(); 791 792 if (keys.size() == 1) { 793 IdField key = keys.get(0); 794 795 key.getType().generateSet(out, pstmt, index, key.getType().generateCastFromObject(var)); 796 } 797 else { 798 for (int i = 0; i < keys.size(); i++) { 799 IdField key = keys.get(i); 800 801 key.getType().generateSet(out, pstmt, index, key.generateGetKeyProperty(var)); 802 } 803 } 804 805 out.popDepth(); 806 out.println("} else {"); 807 out.pushDepth(); 808 809 for (int i = 0; i < keys.size(); i++) { 810 IdField key = keys.get(i); 811 812 key.getType().generateSetNull(out, pstmt, index); 813 } 814 815 out.popDepth(); 816 out.println("}"); 817 } 818 819 822 public void generateUpdateFromObject(JavaWriter out, String obj) 823 throws IOException 824 { 825 String var = "__caucho_field_" + getName(); 826 827 out.println(var + " = " + obj + "." + var + ";"); 828 } 829 830 833 public void generateInvalidateForeign(JavaWriter out) 834 throws IOException 835 { 836 out.println("if (\"" + _targetType.getTable().getName() + "\".equals(table)) {"); 837 out.pushDepth(); 838 839 String loadVar = "__caucho_loadMask_" + (_targetLoadIndex / 64); 840 841 out.println(loadVar + " = 0L;"); 842 out.popDepth(); 843 out.println("}"); 844 } 845 846 849 public void generatePreDelete(JavaWriter out) 850 throws IOException 851 { 852 if (! isTargetCascadeDelete()) 853 return; 854 855 String var = "caucho_field_" + getName(); 856 857 out.println(getJavaTypeName() + " " + var + " = " + getGetterName() + "();"); 858 } 859 860 863 public void generatePostDelete(JavaWriter out) 864 throws IOException 865 { 866 if (! isTargetCascadeDelete()) 867 return; 868 869 String var = "caucho_field_" + getName(); 870 871 out.println("if (" + var + " != null) {"); 872 out.println(" try {"); 873 out.println(" " + var + ".remove();"); 875 out.println(" } catch (Exception e) {"); 876 out.println(" throw com.caucho.amber.AmberRuntimeException.create(e);"); 877 out.println(" }"); 878 out.println("}"); 879 } 880 } 881 | Popular Tags |