1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114
|
/*
* Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2018 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// 05/16/2008-1.0M8 Guy Pelletier
// - 218084: Implement metadata merging functionality between mapping files
// 05/23/2008-1.0M8 Guy Pelletier
// - 211330: Add attributes-complete support to the EclipseLink-ORM.XML Schema
// 09/23/2008-1.1 Guy Pelletier
// - 241651: JPA 2.0 Access Type support
// 01/28/2009-2.0 Guy Pelletier
// - 248293: JPA 2.0 Element Collections (part 1)
// 02/06/2009-2.0 Guy Pelletier
// - 248293: JPA 2.0 Element Collections (part 2)
// 03/27/2009-2.0 Guy Pelletier
// - 241413: JPA 2.0 Add EclipseLink support for Map type attributes
// 04/24/2009-2.0 Guy Pelletier
// - 270011: JPA 2.0 MappedById support
// 04/30/2009-2.0 Michael O'Brien
// - 266912: JPA 2.0 Metamodel API (part of Criteria API)
// 06/16/2009-2.0 Guy Pelletier
// - 277039: JPA 2.0 Cache Usage Settings
// 06/17/2009-2.0 Michael O'Brien
// - 266912: change mappedSuperclassDescriptors Set to a Map
// keyed on MetadataClass - avoiding the use of a hashCode/equals
// override on RelationalDescriptor, but requiring a contains check prior to a put
// 06/25/2009-2.0 Michael O'Brien
// - 266912: change MappedSuperclass handling in stage2 to pre process accessors
// in support of the custom descriptors holding mappings required by the Metamodel
// 08/11/2009-2.0 Michael O'Brien
// - 284147: do not add a pseudo PK Field for MappedSuperclasses when
// 1 or more PK fields already exist on the descriptor.
// 10/21/2009-2.0 Guy Pelletier
// - 290567: mappedbyid support incomplete
// 11/13/2009-2.0 Guy Pelletier
// - 293629: An attribute referenced from orm.xml is not recognized correctly
// 03/08/2010-2.1 Guy Pelletier
// - 303632: Add attribute-type for mapping attributes to EclipseLink-ORM
// 03/08/2010-2.1 Michael O'Brien
// - 300051: JPA 2.0 Metamodel processing requires EmbeddedId validation moved higher from
// EmbeddedIdAccessor.process() to MetadataDescriptor.addAccessor() so we
// can better determine when to add the MAPPED_SUPERCLASS_RESERVED_PK_NAME
// temporary PK field used to process MappedSuperclasses for the Metamodel API
// during MetadataProject.addMetamodelMappedSuperclass()
// 04/09/2010-2.1 Guy Pelletier
// - 307050: Add defaults for access methods of a VIRTUAL access type
// 05/14/2010-2.1 Guy Pelletier
// - 253083: Add support for dynamic persistence using ORM.xml/eclipselink-orm.xml
// 06/09/2010-2.0.3 Guy Pelletier
// - 313401: shared-cache-mode defaults to NONE when the element value is unrecognized
// 06/14/2010-2.2 Guy Pelletier
// - 264417: Table generation is incorrect for JoinTables in AssociationOverrides
// 07/05/2010-2.1.1 Guy Pelletier
// - 317708: Exception thrown when using LAZY fetch on VIRTUAL mapping
// 07/23/2010-2.2 Guy Pelletier
// - 237902: DDL GEN doesn't qualify SEQUENCE table with persistence unit schema
// 08/11/2010-2.2 Guy Pelletier
// - 312123: JPA: Validation error during Id processing on parameterized generic OneToOne Entity relationship from MappedSuperclass
// 09/03/2010-2.2 Guy Pelletier
// - 317286: DB column lenght not in sync between @Column and @JoinColumn
// 12/01/2010-2.2 Guy Pelletier
// - 331234: xml-mapping-metadata-complete overriden by metadata-complete specification
// 12/02/2010-2.2 Guy Pelletier
// - 251554: ExcludeDefaultMapping annotation needed
// 12/02/2010-2.2 Guy Pelletier
// - 324471: Do not default to VariableOneToOneMapping for interfaces unless a managed class implementing it is found
// 03/24/2011-2.3 Guy Pelletier
// - 337323: Multi-tenant with shared schema support (part 1)
// 04/01/2011-2.3 Guy Pelletier
// - 337323: Multi-tenant with shared schema support (part 2)
// 08/09/2011
// Masumi Ito, Fujitsu - Bug 351791 - NPE occurs on specifying two kinds of primary key generators on orm.xml
// 09/09/2011-2.3.1 Guy Pelletier
// - 356197: Add new VPD type to MultitenantType
// 09/20/2011-2.3.1 Guy Pelletier
// - 357476: Change caching default to ISOLATED for multitenant's using a shared EMF.
// 02/08/2012-2.4 Guy Pelletier
// - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
// 06/20/2012-2.5 Guy Pelletier
// - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
// 10/09/2012-2.5 Guy Pelletier
// - 374688: JPA 2.1 Converter support
// 10/30/2012-2.5 Guy Pelletier
// - 374688: JPA 2.1 Converter support
// 11/19/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
// 11/22/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support (index metadata support)
// 02/12/2013-2.5 Guy Pelletier
// - 397772: JPA 2.1 Entity Graph Support (XML support)
// 07/16/2013-2.5.1 Guy Pelletier
// - 412384: Applying Converter for parameterized basic-type for joda-time's DateTime does not work
// 09/01/2014-2.6.0 Dmitry Kornilov
// - JPARS 2.0 related changes
// 12/03/2015-2.6 Dalia Abo Sheasha
// - 483582: Add the javax.persistence.sharedCache.mode property
// 12/05/2016-2.6 Jody Grassel
// - 443546: Converter autoApply does not work for primitive types
package org.eclipse.persistence.internal.jpa.metadata;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_EMBEDDABLE;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.SharedCacheMode;
import javax.persistence.spi.PersistenceUnitInfo;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.dynamic.DynamicType;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ClassAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ConverterAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EmbeddableAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.InterfaceAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.MappedSuperclassAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.DirectCollectionAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.RelationshipAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
import org.eclipse.persistence.internal.jpa.metadata.converters.AbstractConverterMetadata;
import org.eclipse.persistence.internal.jpa.metadata.converters.StructConverterMetadata;
import org.eclipse.persistence.internal.jpa.metadata.listeners.EntityListenerMetadata;
import org.eclipse.persistence.internal.jpa.metadata.partitioning.AbstractPartitioningMetadata;
import org.eclipse.persistence.internal.jpa.metadata.queries.ComplexTypeMetadata;
import org.eclipse.persistence.internal.jpa.metadata.queries.NamedQueryMetadata;
import org.eclipse.persistence.internal.jpa.metadata.queries.SQLResultSetMappingMetadata;
import org.eclipse.persistence.internal.jpa.metadata.sequencing.GeneratedValueMetadata;
import org.eclipse.persistence.internal.jpa.metadata.sequencing.SequenceGeneratorMetadata;
import org.eclipse.persistence.internal.jpa.metadata.sequencing.TableGeneratorMetadata;
import org.eclipse.persistence.internal.jpa.metadata.sequencing.UuidGeneratorMetadata;
import org.eclipse.persistence.internal.jpa.metadata.tables.TableMetadata;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLPersistenceUnitDefaults;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLPersistenceUnitMetadata;
import org.eclipse.persistence.internal.jpa.weaving.RestAdapterClassWriter;
import org.eclipse.persistence.internal.jpa.weaving.RestCollectionAdapterClassWriter;
import org.eclipse.persistence.internal.jpa.weaving.RestReferenceAdapterV2ClassWriter;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredMethod;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.dynamic.JPADynamicTypeBuilder;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sessions.DatasourceLogin;
import org.eclipse.persistence.sessions.Project;
/**
* INTERNAL:
* A MetadataProject stores metadata and also helps to facilitate the metadata
* processing.
*
* Key notes:
* - Care should be taken when using Sets to hold metadata and checking their
* equality. In most cases you should be able to us a List or Map since most
* additions to those lists should not occur multiple times for the same
* object. Just be aware of what you are gathering and how. For example, for
* ClassAccessors, they can always be stored in a map keyed on
* accessor.getJavaClassName(). List of mapping accessors is ok as well since
* in most cases we check isProcessed() before calling process on them etc.
* - methods should be preserved in alphabetical order.
*
* @author Guy Pelletier
* @since TopLink EJB 3.0 Reference Implementation
*/
public class MetadataProject {
// Sequencing constants.
public static final String DEFAULT_AUTO_GENERATOR = "SEQ_GEN";
public static final String DEFAULT_TABLE_GENERATOR = "SEQ_GEN_TABLE";
public static final String DEFAULT_SEQUENCE_GENERATOR = "SEQ_GEN_SEQUENCE";
public static final String DEFAULT_IDENTITY_GENERATOR = "SEQ_GEN_IDENTITY";
// Boolean to specify if we should weave fetch groups.
private boolean m_isWeavingFetchGroupsEnabled;
// Boolean to specify if the user intends for the related EMF of this
// project to be shared for multitenants.
private boolean m_multitenantSharedEmf;
// Boolean to specify if the user intends for the related EMF cache of this
// project to be shared for multitenants.
private boolean m_multitenantSharedCache;
// Boolean to specify if we should weave eager relationships.
private boolean m_isWeavingEagerEnabled;
// Boolean to specify if we should weave lazy relationships.
private boolean m_isWeavingLazyEnabled;
// Boolean to specify if we should uppercase all field names.
// @see PersistenceUnitProperties.UPPERCASE_COLUMN_NAMES
private boolean m_forceFieldNamesToUpperCase;
// Cache the shared cache mode
private SharedCacheMode m_sharedCacheMode;
private boolean m_isSharedCacheModeInitialized;
// A composite PU processor.
private MetadataProcessor m_compositeProcessor;
// Persistence unit info that is represented by this project.
private PersistenceUnitInfo m_persistenceUnitInfo;
// The session we are currently processing for.
private AbstractSession m_session;
// The logger for the project.
private MetadataLogger m_logger;
// Persistence unit metadata for this project.
private XMLPersistenceUnitMetadata m_persistenceUnitMetadata;
// All owning relationship accessors.
private List<RelationshipAccessor> m_owningRelationshipAccessors;
// All non-owning (mappedBy) relationship accessors.
private List<RelationshipAccessor> m_nonOwningRelationshipAccessors;
// Accessors that map to an Embeddable class
private List<MappingAccessor> m_embeddableMappingAccessors;
// All direct collection accessors.
private List<DirectCollectionAccessor> m_directCollectionAccessors;
// Class accessors that have a customizer.
private List<ClassAccessor> m_accessorsWithCustomizer;
// A linked map of all the entity mappings (XML file representation)
private Map<String, XMLEntityMappings> m_entityMappings;
// Map of mapped-superclasses found in XML for this project/persistence unit.
private Map<String, MappedSuperclassAccessor> m_mappedSuperclasseAccessors;
// All the class accessors for this project (Entities and Embeddables).
private Map<String, ClassAccessor> m_allAccessors;
// The entity accessors for this project
private Map<String, EntityAccessor> m_entityAccessors;
// Contains those embeddables and entities that are VIRTUAL (do not exist)
private Map<String, ClassAccessor> m_virtualClasses;
// The embeddable accessors for this project
private Map<String, EmbeddableAccessor> m_embeddableAccessors;
// Root level embeddable accessors. When we pre-process embeddable
// accessors we need to process them from the root down so as to set
// the correct owning descriptor.
private Map<String, EmbeddableAccessor> m_rootEmbeddableAccessors;
// The interface accessors for this project
private Map<String, InterfaceAccessor> m_interfaceAccessors;
// Class accessors that have their id derived from a relationship.
private Map<String, ClassAccessor> m_accessorsWithDerivedId;
// Query metadata.
private Map<String, NamedQueryMetadata> m_queries;
// SQL result set mapping
private Map<String, SQLResultSetMappingMetadata> m_sqlResultSetMappings;
// Sequencing metadata.
private Map<MetadataClass, GeneratedValueMetadata> m_generatedValues;
private Map<String, TableGeneratorMetadata> m_tableGenerators;
private Map<String, SequenceGeneratorMetadata> m_sequenceGenerators;
private Map<String, UuidGeneratorMetadata> m_uuidGenerators;
// Metadata converters, that is, EclipseLink converters.
private Map<String, AbstractConverterMetadata> m_converters;
// The converter accessors for this project
private Map<String, ConverterAccessor> m_converterAccessors;
private Map<String, ConverterAccessor> m_autoApplyConvertAccessors;
// Store PLSQL record and table types, Oracle object types,
// array types and XMLType types by name, to allow reuse.
private Map<String, ComplexTypeMetadata> m_complexMetadataTypes;
// Store partitioning policies by name, to allow reuse.
private Map<String, AbstractPartitioningMetadata> m_partitioningPolicies;
// All mappedSuperclass accessors, identity is handled by keying on className.
private Map<String, MappedSuperclassAccessor> m_metamodelMappedSuperclasses;
// All id classes (IdClass and EmbeddedId classes) used through-out the
// persistence unit. We need this list to determine derived id accessors.
private Set<String> m_idClasses;
// Contains a list of all interfaces that are implemented by entities in
// this project/pu.
private Set<String> m_interfacesImplementedByEntities;
// Default listeners that need to be applied to each entity in the
// persistence unit (unless they exclude them).
private Set<EntityListenerMetadata> m_defaultListeners;
public void createRestInterfaces(ClassLoader loader) {
if (DynamicClassLoader.class.isAssignableFrom(loader.getClass())) {
DynamicClassLoader dcl = (DynamicClassLoader) loader;
for (EntityAccessor accessor : getEntityAccessors()) {
String className = accessor.getParentClassName();
if (className == null || getEntityAccessor(className) == null) {
// Reference adapter for JPARS version < 2.0
RestAdapterClassWriter restAdapter = new RestAdapterClassWriter(accessor.getJavaClassName());
dcl.addClass(restAdapter.getClassName(), restAdapter);
}
}
for (ClassAccessor classAccessor : getAllAccessors()) {
String className = classAccessor.getParentClassName();
if (className == null || getEntityAccessor(className) == null) {
// Collection adapter for JPARS version >= 2.0
RestCollectionAdapterClassWriter restCollectionAdapter = new RestCollectionAdapterClassWriter(classAccessor.getJavaClassName());
dcl.addClass(restCollectionAdapter.getClassName(), restCollectionAdapter);
// Reference adapter for JPARS version >= 2.0
RestReferenceAdapterV2ClassWriter restReferenceAdapterV2 = new RestReferenceAdapterV2ClassWriter(classAccessor.getJavaClassName());
dcl.addClass(restReferenceAdapterV2.getClassName(), restReferenceAdapterV2);
}
}
}
}
/**
* INTERNAL:
* Create and return a new MetadataProject with puInfo as its PersistenceUnitInfo,
* session as its Session and weavingEnabled as its global dynamic weaving state.
* @param puInfo - the PersistenceUnitInfo
* @param session - the Session
*/
public MetadataProject(PersistenceUnitInfo puInfo, AbstractSession session, boolean weaveLazy, boolean weaveEager, boolean weaveFetchGroups, boolean multitenantSharedEmf, boolean multitenantSharedCache) {
m_isSharedCacheModeInitialized = false;
m_persistenceUnitInfo = puInfo;
m_session = session;
m_logger = new MetadataLogger(session);
m_isWeavingEagerEnabled = weaveEager;
m_isWeavingLazyEnabled = weaveLazy;
m_isWeavingFetchGroupsEnabled = weaveFetchGroups;
m_multitenantSharedEmf = multitenantSharedEmf;
m_multitenantSharedCache = multitenantSharedCache;
m_owningRelationshipAccessors = new ArrayList<RelationshipAccessor>();
m_nonOwningRelationshipAccessors = new ArrayList<RelationshipAccessor>();
m_embeddableMappingAccessors = new ArrayList<MappingAccessor>();
m_directCollectionAccessors = new ArrayList<DirectCollectionAccessor>();
m_accessorsWithCustomizer = new ArrayList<ClassAccessor>();
// Using linked collections since their ordering needs to be preserved.
m_entityMappings = new LinkedHashMap<String, XMLEntityMappings>();
m_defaultListeners = new LinkedHashSet<EntityListenerMetadata>();
m_queries = new HashMap<String, NamedQueryMetadata>();
m_sqlResultSetMappings = new HashMap<String, SQLResultSetMappingMetadata>();
m_allAccessors = new HashMap<String, ClassAccessor>();
m_entityAccessors = new HashMap<String, EntityAccessor>();
m_embeddableAccessors = new HashMap<String, EmbeddableAccessor>();
m_rootEmbeddableAccessors = new HashMap<String, EmbeddableAccessor>();
m_interfaceAccessors = new HashMap<String, InterfaceAccessor>();
m_mappedSuperclasseAccessors = new HashMap<String, MappedSuperclassAccessor>();
m_generatedValues = new HashMap<MetadataClass, GeneratedValueMetadata>();
m_tableGenerators = new HashMap<String, TableGeneratorMetadata>();
m_sequenceGenerators = new HashMap<String, SequenceGeneratorMetadata>();
m_uuidGenerators = new HashMap<String, UuidGeneratorMetadata>();
m_converters = new HashMap<String, AbstractConverterMetadata>();
m_converterAccessors = new HashMap<String, ConverterAccessor>();
m_autoApplyConvertAccessors = new HashMap<String, ConverterAccessor>();
m_partitioningPolicies = new HashMap<String, AbstractPartitioningMetadata>();
m_complexMetadataTypes = new HashMap<String, ComplexTypeMetadata>();
m_metamodelMappedSuperclasses = new HashMap<String, MappedSuperclassAccessor>();
m_virtualClasses = new HashMap<String, ClassAccessor>();
m_accessorsWithDerivedId = new HashMap<String, ClassAccessor>();
m_idClasses = new HashSet<String>();
m_interfacesImplementedByEntities = new HashSet<String>();
}
/**
* INTERNAL:
* This method will add the descriptor to the actual EclipseLink project,
* if it has not already been added. This method if called for entities
* and embeddable classes (which are both weavable classes).
*/
protected void addAccessor(ClassAccessor accessor) {
MetadataDescriptor descriptor = accessor.getDescriptor();
// Process the persistence unit meta data (if there is any).
processPersistenceUnitMetadata(descriptor);
// Process and set the parent class (if one is available).
accessor.processParentClass();
// Add the descriptor to the actual EclipseLink Project.
m_session.getProject().addDescriptor(descriptor.getClassDescriptor());
// Keep a map of all the accessors that have been added.
m_allAccessors.put(accessor.getJavaClassName(), accessor);
}
/**
* INTERNAL:
*/
public void addAccessorWithCustomizer(ClassAccessor accessor) {
m_accessorsWithCustomizer.add(accessor);
}
/**
* INTERNAL:
*/
public void addAccessorWithDerivedId(ClassAccessor accessor) {
m_accessorsWithDerivedId.put(accessor.getJavaClassName(), accessor);
}
/**
* INTERNAL:
*/
public void addAlias(String alias, MetadataDescriptor descriptor) {
ClassDescriptor existingDescriptor = m_session.getProject().getDescriptorForAlias(alias);
if (existingDescriptor == null) {
descriptor.setAlias(alias);
m_session.getProject().addAlias(alias, descriptor.getClassDescriptor());
} else {
throw ValidationException.nonUniqueEntityName(existingDescriptor.getJavaClassName(), descriptor.getJavaClassName(), alias);
}
}
/**
* INTERNAL:
* Add a abstract converter metadata to the project. The actual processing
* isn't done until an accessor referencing the converter is processed.
*/
public void addConverter(AbstractConverterMetadata converter) {
// Check for another converter with the same name.
if (converter.shouldOverride(m_converters.get(converter.getName()))) {
m_converters.put(converter.getName(), converter);
}
}
/**
* INTERNAL:
* Add a abstract converter metadata to the project. The actual processing
* isn't done until an accessor referencing the converter is processed.
*/
public void addConverterAccessor(ConverterAccessor converterAccessor) {
// Check for another converter with the same name.
if (converterAccessor.shouldOverride(m_converterAccessors.get(converterAccessor.getIdentifier()))) {
m_converterAccessors.put(converterAccessor.getIdentifier(), converterAccessor);
}
}
/**
* INTERNAL:
*/
public void addDefaultListener(EntityListenerMetadata defaultListener) {
m_defaultListeners.add(defaultListener);
}
/**
* INTERNAL:
* Store basic collection accessors for later processing and quick look up.
*/
public void addDirectCollectionAccessor(MappingAccessor accessor) {
m_directCollectionAccessors.add((DirectCollectionAccessor) accessor);
}
/**
* INTERNAL:
* Add an embeddable accessor to this project. Assumes the embeddable
* needs to be added. That is, does not check if it already exists and
* cause a merge. The caller is responsible for that.
*/
public void addEmbeddableAccessor(EmbeddableAccessor accessor) {
// Add accessor will apply persistence unit defaults.
addAccessor(accessor);
accessor.getDescriptor().setIsEmbeddable();
m_embeddableAccessors.put(accessor.getJavaClassName(), accessor);
}
/**
* INTERNAL:
*/
public void addEmbeddableMappingAccessor(MappingAccessor accessor) {
m_embeddableMappingAccessors.add(accessor);
}
/**
* INTERNAL:
* Add an entity accessor to this project. Assumes the entity needs to be
* added. That is, does not check if it already exists and cause a merge.
* The caller is responsible for that.
*/
public void addEntityAccessor(EntityAccessor accessor) {
// Add accessor will apply persistence unit defaults.
addAccessor(accessor);
// Grab the implemented interfaces (used when defaulting v1-1 mappings)
m_interfacesImplementedByEntities.addAll(accessor.getJavaClass().getInterfaces());
m_entityAccessors.put(accessor.getJavaClassName(), accessor);
}
/**
* INTERNAL:
* Add the given entity graph (internal attribute group).
*/
public void addEntityGraph(AttributeGroup entityGraph) {
getProject().getAttributeGroups().put(entityGraph.getName(), entityGraph);
}
/**
* INTERNAL:
* The avoid processing the same mapping file twice (e.g. user may
* explicitly specify the orm.xml file) we store the list of entity
* mappings in a map keyed on their URL.
*/
public void addEntityMappings(XMLEntityMappings entityMappings) {
// Add the new entity mappings file to the list.
m_entityMappings.put(entityMappings.getMappingFileOrURL(), entityMappings);
}
/**
* INTERNAL:
*/
public void addGeneratedValue(GeneratedValueMetadata generatedvalue, MetadataClass entityClass) {
m_generatedValues.put(entityClass, generatedvalue);
}
/**
* INTERNAL:
* Add EmbeddedId and IdClass ids to the project
*/
public void addIdClass(String idClassName) {
m_idClasses.add(idClassName);
}
/**
* INTERNAL:
* Add a InterfaceAccessor to this project.
*/
public void addInterfaceAccessor(InterfaceAccessor accessor) {
m_interfaceAccessors.put(accessor.getJavaClassName(), accessor);
// Add it directly and avoid the persistence unit defaults and stuff for now.
m_session.getProject().addDescriptor(accessor.getDescriptor().getClassDescriptor());
}
/**
* INTERNAL:
* Add a mapped superclass accessor to this project. Assumes the mapped
* superclass needs to be added. That is, does not check if it already
* exists and cause a merge. The caller is responsible for that. At runtime,
* this map will contain mapped superclasses from XML only. The canonical
* model processor will populate all mapped superclasses in this map.
*/
public void addMappedSuperclass(MappedSuperclassAccessor mappedSuperclass) {
// Process and set the parent class (if one is available).
mappedSuperclass.processParentClass();
m_mappedSuperclasseAccessors.put(mappedSuperclass.getJavaClassName(), mappedSuperclass);
// add the mapped superclass to keep track of it in case it is not processed later (has no subclasses).
m_session.getProject().addMappedSuperclass(mappedSuperclass.getJavaClassName(), mappedSuperclass.getDescriptor().getClassDescriptor(), false);
}
/**
* INTERNAL:
* The metamodel API requires that descriptors exist for mappedSuperclasses
* in order to obtain their mappings.<p>
* In order to accomplish this, this method that is called from EntityAccessor
* will ensure that the descriptors on all mappedSuperclass accessors
* are setup so that they can be specially processed later in
* MetadataProject.processStage2() - where the m_mappedSuperclassAccessors
* Map is required.
* <p>
* We do not use the non-persisting MAPPED_SUPERCLASS_RESERVED_PK_NAME PK field.
* Normally when the MappedSuperclass is part of an inheritance hierarchy of the form MS->MS->E,
* where there is an PK Id on the root Entity E, we need to add the
* MAPPED_SUPERCLASS_RESERVED_PK_NAME PK field solely for metadata processing to complete.
* Why? because even though we treat MappedSuperclass objects as a RelationalDescriptor - we only persist
* RelationalDescriptor objects that relate to concrete Entities.
* <p>
* This method is referenced by EntityAccessor.addPotentialMappedSuperclass()
* during an initial predeploy() and later during a deploy()
* </p>
* @param accessor - The mappedSuperclass accessor for the field on the mappedSuperclass<p>
* @since EclipseLink 1.2 for the JPA 2.0 Reference Implementation
*/
public void addMetamodelMappedSuperclass(MappedSuperclassAccessor accessor, MetadataDescriptor childDescriptor) {
// Check for an existing entry before proceeding. Metamodel mapped
// superclasses need only (and should only) be added once. This code
// will be called from every entity that inherits from it. There is no
// need to check for className == null here as the mapped superclass
// accessor is always created with a class.
if (! m_metamodelMappedSuperclasses.containsKey(accessor.getJavaClassName())) {
MetadataDescriptor metadataDescriptor = accessor.getDescriptor();
// Set a child entity descriptor on the mapped superclass descriptor.
// This descriptor (and its mapping accessors) will help to resolve
// any generic mapping accessors from the mapped superclass.
metadataDescriptor.setMetamodelMappedSuperclassChildDescriptor(childDescriptor);
// Note: set the back pointer from the MetadataDescriptor back to its' accessor manually before we add accessors
metadataDescriptor.setClassAccessor(accessor);
// Make sure you apply the persistence unit metadata and defaults.
processPersistenceUnitMetadata(metadataDescriptor);
// Need to apply the mapping file defaults (if there is one that loaded this mapped superclass).
if (accessor.getEntityMappings() != null) {
accessor.getEntityMappings().processEntityMappingsDefaults(accessor);
}
// After the pu metadata and defaults have been applied, it is safe to process the access type.
accessor.processAccessType();
// Set the referenceClass for Id mappings
// Generics Handler: Check if the referenceType is not set for Collection accessors
accessor.addAccessors();
// Add the accessor to our custom Map keyed on className for separate processing in stage2
m_metamodelMappedSuperclasses.put(accessor.getJavaClassName(), accessor);
// Fake out a database table and primary key for MappedSuperclasses
// We require string names for table processing that does not actually goto the database.
// There will be no conflict with customer values
// The descriptor is assumed never to be null
metadataDescriptor.setPrimaryTable(new DatabaseTable(MetadataConstants.MAPPED_SUPERCLASS_RESERVED_TABLE_NAME));
/*
* We need to add a PK field to the temporary mappedsuperclass table above - in order to continue processing.
* Note: we add this field only if no IdClass or EmbeddedId attributes are set on or above the MappedSuperclass.
* Both the table name and PK name are not used to actual database writes.
* Check accessor collection on the metadataDescriptor (note: getIdAttributeName() and getIdAttributeNames() are not populated yet - so are unavailable
* 300051: The check for at least one IdAccessor or an EmbeddedIdAccessor requires that the map and field respectively
* are set previously in MetadataDescriptor.addAccessor().
* The checks below will also avoid a performance hit on searching the accessor map directly on the descriptor.
*/
if (!metadataDescriptor.hasIdAccessor() && !metadataDescriptor.hasEmbeddedId()) {
DatabaseField pkField = new DatabaseField(MetadataConstants.MAPPED_SUPERCLASS_RESERVED_PK_NAME);
if (this.useDelimitedIdentifier()) {
pkField.setUseDelimiters(true);
} else if (this.getShouldForceFieldNamesToUpperCase()) {
pkField.useUpperCaseForComparisons(true);
}
metadataDescriptor.addPrimaryKeyField(pkField);
}
/*
* We store our descriptor on the core project for later retrieval by MetamodelImpl.
* Why not on MetadataProject? because the Metadata processing is transient.
* We could set the javaClass on the descriptor for the current classLoader
* but we do not need it until metamodel processing time avoiding a _persistence_new call.
* See MetamodelImpl.initialize()
*/
m_session.getProject().addMappedSuperclass(accessor.getJavaClassName(), metadataDescriptor.getClassDescriptor(), true);
}
}
/**
* INTERNAL:
* Add the partitioning policy by name.
*/
public void addPartitioningPolicy(AbstractPartitioningMetadata policy) {
// Check for another policy with the same name.
if (policy.shouldOverride(m_partitioningPolicies.get(policy.getName()))) {
m_partitioningPolicies.put(policy.getName(), policy);
}
}
/**
* INTERNAL:
* Add the named PLSQL or Oracle complex metadata type.
*/
public void addComplexMetadataType(ComplexTypeMetadata type) {
// Check for another type with the same name.
if (type.shouldOverride(m_complexMetadataTypes.get(type.getName()))) {
m_complexMetadataTypes.put(type.getName(), type);
}
}
/**
* INTERNAL:
* Add a query to the project overriding where necessary.
*/
public void addQuery(NamedQueryMetadata query) {
if (query.shouldOverride(m_queries.get(query.getName()))) {
m_queries.put(query.getName(), query);
}
}
/**
* INTERNAL:
*/
public void addRelationshipAccessor(RelationshipAccessor accessor) {
if (accessor.hasMappedBy()) {
m_nonOwningRelationshipAccessors.add(accessor);
} else {
m_owningRelationshipAccessors.add(accessor);
}
}
/**
* INTERNAL:
* Add a root level embeddable accessor.
*/
public void addRootEmbeddableAccessor(EmbeddableAccessor accessor) {
m_rootEmbeddableAccessors.put(accessor.getJavaClassName(), accessor);
}
/**
* INTERNAL:
* Add a sequence generator metadata to the project. The actual processing
* isn't done till processSequencing is called.
*/
public void addSequenceGenerator(SequenceGeneratorMetadata sequenceGenerator, String defaultCatalog, String defaultSchema) {
String name = sequenceGenerator.getName();
// Check if the sequence generator name uses a reserved name.
if (name.equals(DEFAULT_TABLE_GENERATOR)) {
throw ValidationException.sequenceGeneratorUsingAReservedName(DEFAULT_TABLE_GENERATOR, sequenceGenerator.getLocation());
} else if (name.equals(DEFAULT_IDENTITY_GENERATOR)) {
throw ValidationException.sequenceGeneratorUsingAReservedName(DEFAULT_IDENTITY_GENERATOR, sequenceGenerator.getLocation());
}
// Catalog could be "" or null, need to check for an XML default.
sequenceGenerator.setCatalog(MetadataHelper.getName(sequenceGenerator.getCatalog(), defaultCatalog, sequenceGenerator.getCatalogContext(), m_logger, sequenceGenerator.getLocation()));
// Schema could be "" or null, need to check for an XML default.
sequenceGenerator.setSchema(MetadataHelper.getName(sequenceGenerator.getSchema(), defaultSchema, sequenceGenerator.getSchemaContext(), m_logger, sequenceGenerator.getLocation()));
// Check if the name is used with a table generator.
TableGeneratorMetadata tableGenerator = m_tableGenerators.get(name);
if (tableGenerator != null) {
if (sequenceGenerator.shouldOverride(tableGenerator)) {
m_tableGenerators.remove(name);
} else {
throw ValidationException.conflictingSequenceAndTableGeneratorsSpecified(name, sequenceGenerator.getLocation(), tableGenerator.getLocation());
}
}
for (TableGeneratorMetadata otherTableGenerator : m_tableGenerators.values()) {
if ((tableGenerator != otherTableGenerator) && (otherTableGenerator.getPkColumnValue() != null) && otherTableGenerator.getPkColumnValue().equals(sequenceGenerator.getSequenceName())) { // generator name will be used instead of an empty sequence name / pk column name
// generator name will be used instead of an empty sequence name / pk column name
if (otherTableGenerator.getPkColumnValue().length() > 0) {
throw ValidationException.conflictingSequenceNameAndTablePkColumnValueSpecified(sequenceGenerator.getSequenceName(), sequenceGenerator.getLocation(), otherTableGenerator.getLocation());
}
}
}
// Add the sequence generator if there isn't an existing one or if
// we should override an existing one.
if (sequenceGenerator.shouldOverride(m_sequenceGenerators.get(name))) {
m_sequenceGenerators.put(sequenceGenerator.getName(), sequenceGenerator);
}
}
/**
* INTERNAL:
* Add a UUID generator metadata to the project. The actual processing
* isn't done till processSequencing is called.
*/
public void addUuidGenerator(UuidGeneratorMetadata uuidGenerator) {
String name = uuidGenerator.getName();
// Check if the name is used with a table generator.
TableGeneratorMetadata tableGenerator = m_tableGenerators.get(name);
if (tableGenerator != null) {
if (uuidGenerator.shouldOverride(tableGenerator)) {
m_tableGenerators.remove(name);
} else {
throw ValidationException.conflictingSequenceAndTableGeneratorsSpecified(name, uuidGenerator.getLocation(), tableGenerator.getLocation());
}
}
m_uuidGenerators.put(uuidGenerator.getName(), uuidGenerator);
}
/**
* INTERNAL:
* Add an sql results set mapping to the project overriding where necessary.
*/
public void addSQLResultSetMapping(SQLResultSetMappingMetadata sqlResultSetMapping) {
if (sqlResultSetMapping.shouldOverride(m_sqlResultSetMappings.get(sqlResultSetMapping.getName()))) {
m_sqlResultSetMappings.put(sqlResultSetMapping.getName(), sqlResultSetMapping);
}
}
/**
* INTERNAL:
* Add a discovered metamodel class to the session.
*/
public void addStaticMetamodelClass(MetadataAnnotation annotation, MetadataClass metamodelClass) {
MetadataClass modelClass = metamodelClass.getMetadataClass(annotation.getAttributeString("value"));
m_session.addStaticMetamodelClass(modelClass.getName(), metamodelClass.getName());
}
/**
* INTERNAL:
* Add a table generator metadata to the project. The actual processing
* isn't done till processSequencing is called.
*/
public void addTableGenerator(TableGeneratorMetadata tableGenerator, String defaultCatalog, String defaultSchema) {
// Process the default values.
processTable(tableGenerator, "", defaultCatalog, defaultSchema, tableGenerator);
String generatorName = tableGenerator.getGeneratorName();
// Check if the table generator name uses a reserved name.
if (generatorName.equals(DEFAULT_SEQUENCE_GENERATOR)) {
throw ValidationException.tableGeneratorUsingAReservedName(DEFAULT_SEQUENCE_GENERATOR, tableGenerator.getLocation());
} else if (generatorName.equals(DEFAULT_IDENTITY_GENERATOR)) {
throw ValidationException.tableGeneratorUsingAReservedName(DEFAULT_IDENTITY_GENERATOR, tableGenerator.getLocation());
}
// Check if the generator name is used with a sequence generator.
SequenceGeneratorMetadata otherSequenceGenerator = m_sequenceGenerators.get(generatorName);
if (otherSequenceGenerator != null) {
if (tableGenerator.shouldOverride(otherSequenceGenerator)) {
m_sequenceGenerators.remove(generatorName);
} else {
throw ValidationException.conflictingSequenceAndTableGeneratorsSpecified(generatorName, otherSequenceGenerator.getLocation(), tableGenerator.getLocation());
}
}
for (SequenceGeneratorMetadata sequenceGenerator : m_sequenceGenerators.values()) {
if ((otherSequenceGenerator != sequenceGenerator) && (sequenceGenerator.getSequenceName() != null) && sequenceGenerator.getSequenceName().equals(tableGenerator.getPkColumnValue())) {
// generator name will be used instead of an empty sequence name / pk column name
if (sequenceGenerator.getSequenceName().length() > 0) {
throw ValidationException.conflictingSequenceNameAndTablePkColumnValueSpecified(sequenceGenerator.getSequenceName(), sequenceGenerator.getLocation(), tableGenerator.getLocation());
}
}
}
// Add the table generator if there isn't an existing one or if we
// should override an existing one.
if (tableGenerator.shouldOverride(m_tableGenerators.get(generatorName))) {
m_tableGenerators.put(generatorName, tableGenerator);
}
}
/**
* INTERNAL:
* Add virtual class accessor to the project. A virtual class is one that
* has VIRTUAL access and the class does not exist on the classpath.
*/
public void addVirtualClass(ClassAccessor accessor) {
m_virtualClasses.put(accessor.getJavaClassName(), accessor);
}
/**
* INTERNAL:
* Create the dynamic class using JPA metadata processed descriptors. Called
* at deploy time after all metadata processing has completed.
*/
protected void createDynamicClass(MetadataDescriptor descriptor, Map<String, MetadataDescriptor> virtualEntities, DynamicClassLoader dcl) {
// Build the virtual class only if we have not already done so.
if (! virtualEntities.containsKey(descriptor.getJavaClassName())) {
if (descriptor.isInheritanceSubclass()) {
// Get the parent descriptor.
MetadataDescriptor parentDescriptor = descriptor.getInheritanceParentDescriptor();
// Recursively call up the parents.
createDynamicClass(parentDescriptor, virtualEntities, dcl);
// Create and set the virtual class using the parent class.
descriptor.getClassDescriptor().setJavaClass(dcl.createDynamicClass(descriptor.getJavaClassName(), parentDescriptor.getClassDescriptor().getJavaClass()));
} else {
// Create and set the virtual class on the descriptor
descriptor.getClassDescriptor().setJavaClass(dcl.createDynamicClass(descriptor.getJavaClassName(), new MetadataDynamicClassWriter(descriptor)));
}
// Store the descriptor by java class name.
virtualEntities.put(descriptor.getJavaClassName(), descriptor);
}
}
/**
* INTERNAL:
* Create the dynamic class using JPA metadata processed descriptors. Called
* at deploy time after all metadata processing has completed.
*/
public void createDynamicClasses(ClassLoader loader) {
if (! m_virtualClasses.isEmpty()) {
if (DynamicClassLoader.class.isAssignableFrom(loader.getClass())) {
DynamicClassLoader dcl = (DynamicClassLoader) loader;
// Create the dynamic classes.
Map<String, MetadataDescriptor> dynamicClasses = new HashMap<String, MetadataDescriptor>();
for (ClassAccessor accessor : m_virtualClasses.values()) {
createDynamicClass(accessor.getDescriptor(), dynamicClasses, dcl);
}
// Create the dynamic types.
Map<String, DynamicType> dynamicTypes = new HashMap<String, DynamicType>();
for (MetadataDescriptor descriptor : dynamicClasses.values()) {
createDynamicType(descriptor, dynamicTypes, dcl);
}
} else {
// If we have virtual classes that need creation and we do not
// have a dynamic class loader throw an exception.
throw ValidationException.invalidClassLoaderForDynamicPersistence();
}
}
}
/**
* INTERNAL:
* Create the dynamic types using JPA metadata processed descriptors. Called
* at deploy time after all metadata processing has completed.
*/
protected void createDynamicType(MetadataDescriptor descriptor, Map<String, DynamicType> dynamicTypes, DynamicClassLoader dcl) {
// Build the dynamic class only if we have not already done so.
if (! dynamicTypes.containsKey(descriptor.getJavaClassName())) {
JPADynamicTypeBuilder typeBuilder = null;
if (descriptor.isInheritanceSubclass()) {
// Get the parent descriptor
MetadataDescriptor parentDescriptor = descriptor.getInheritanceParentDescriptor();
// Recursively call up the parents.
createDynamicType(parentDescriptor, dynamicTypes, dcl);
// Create the dynamic type using the parent type.
typeBuilder = new JPADynamicTypeBuilder(dcl, descriptor.getClassDescriptor(), dynamicTypes.get(parentDescriptor.getJavaClassName()));
} else {
// Create the dynamic type
typeBuilder = new JPADynamicTypeBuilder(dcl, descriptor.getClassDescriptor(), null);
}
// Store the type builder by java class name.
dynamicTypes.put(descriptor.getJavaClassName(), typeBuilder.getType());
}
}
/**
* INTERNAL:
* Set if the project should use indirection for lazy relationships.
*/
public void disableWeaving() {
m_isWeavingLazyEnabled = false;
m_isWeavingEagerEnabled = false;
m_isWeavingFetchGroupsEnabled = false;
}
/**
* INTERNAL:
* Return true if an exclude-default-mappings setting have been set for this
* persistence unit.
*/
public boolean excludeDefaultMappings() {
if (m_persistenceUnitMetadata != null) {
return m_persistenceUnitMetadata.excludeDefaultMappings();
}
return false;
}
/**
* INTERNAL:
* Return the accessor for the given class. Could be an entity or an
* embeddable. Note: It may return null.
*/
public ClassAccessor getAccessor(String className) {
return m_allAccessors.get(className);
}
/**
* INTERNAL:
*/
public List<ClassAccessor> getAccessorsWithCustomizer() {
return m_accessorsWithCustomizer;
}
/**
* INTERNAL:
*/
public Collection<ClassAccessor> getAllAccessors() {
return m_allAccessors.values();
}
/**
* Return the converter for the auto apply class type.
*/
public ConverterAccessor getAutoApplyConverter(MetadataClass cls) {
ConverterAccessor ca = m_autoApplyConvertAccessors.get(cls.getName());
if (ca == null) {
String wrapperType = resolvePrimitiveWrapper(cls);
if (wrapperType != null) {
ca = m_autoApplyConvertAccessors.get(wrapperType);
}
}
return ca;
}
private String resolvePrimitiveWrapper(MetadataClass cls) {
String wrapperType = null;
if (cls.isPrimitive() && !cls.isArray() && !m_autoApplyConvertAccessors.isEmpty()) {
// Look for Converters for the Wrapper equivalent of the primitive
switch (cls.getTypeName()) {
case "I": // int
wrapperType = "java.lang.Integer";
break;
case "J": // long
wrapperType = "java.lang.Long";
break;
case "S": // short
wrapperType = "java.lang.Short";
break;
case "Z": // boolean
wrapperType = "java.lang.Boolean";
break;
case "F": // float
wrapperType = "java.lang.Float";
break;
case "D": // double
wrapperType = "java.lang.Double";
break;
case "C": // char
wrapperType = "java.lang.Character";
break;
case "B": // byte
wrapperType = "java.lang.Byte";
break;
default: // unknown
}
}
return wrapperType;
}
/**
* INTERNAL:
*/
public MetadataProcessor getCompositeProcessor() {
return m_compositeProcessor;
}
/**
* INTERNAL:
*/
public AbstractConverterMetadata getConverter(String name) {
return m_converters.get(name);
}
/**
* INTERNAL:
*/
public ConverterAccessor getConverterAccessor(MetadataClass cls) {
return m_converterAccessors.get(cls.getName());
}
/**
* INTERNAL:
*/
public Map<String, ConverterAccessor> getConverterAccessors() {
return m_converterAccessors;
}
/**
* INTERNAL:
*/
public Set<EntityListenerMetadata> getDefaultListeners() {
return m_defaultListeners;
}
/**
* INTERNAL:
* This method will attempt to look up the embeddable accessor for the
* reference class provided. If no accessor is found, null is returned.
*/
public EmbeddableAccessor getEmbeddableAccessor(MetadataClass cls) {
return getEmbeddableAccessor(cls, false);
}
/**
* INTERNAL:
* This method will attempt to look up the embeddable accessor for the
* reference class provided. If no accessor is found, null is returned.
*/
public EmbeddableAccessor getEmbeddableAccessor(MetadataClass cls, boolean checkIsIdClass) {
EmbeddableAccessor accessor = m_embeddableAccessors.get(cls.getName());
if (accessor == null) {
// Before we return null we must make a couple final checks:
//
// 1 - Check for an Embeddable annotation on the class itself. At
// this point we know the class was not tagged as an embeddable in
// a mapping file and was not included in the list of classes for
// this persistence unit. Its inclusion therefore in the persistence
// unit is through the use of an Embedded annotation or an embedded
// element within a known entity.
// 2 - If checkIsIdClass is true, JPA 2.0 introduced support for
//
// derived id's where a parent entity's id class may be used within
// a dependants embedded id class. We will treat the id class as
// and embeddable accessor at this point.
//
// Callers to this method will have to handle the null case if they
// so desire.
if (cls.isAnnotationPresent(JPA_EMBEDDABLE) || (checkIsIdClass && isIdClass(cls))) {
accessor = new EmbeddableAccessor(cls.getAnnotation(JPA_EMBEDDABLE), cls, this);
addEmbeddableAccessor(accessor);
}
}
return accessor;
}
/**
* INTERNAL:
* Return the embeddable accessor with the given classname.
*/
public EmbeddableAccessor getEmbeddableAccessor(String className) {
return m_embeddableAccessors.get(className);
}
/**
* INTERNAL:
* Return the embeddable accessor with the given classname.
*/
public Collection<EmbeddableAccessor> getEmbeddableAccessors() {
return m_embeddableAccessors.values();
}
/**
* INTERNAL:
* Return the entity accessor for the given class name.
*/
public EntityAccessor getEntityAccessor(MetadataClass cls) {
return getEntityAccessor(cls.getName());
}
/**
* INTERNAL:
* Return the entity accessor for the given class name.
*/
public EntityAccessor getEntityAccessor(String className) {
return m_entityAccessors.get(className);
}
/**
* INTERNAL:
*/
public Collection<EntityAccessor> getEntityAccessors() {
return m_entityAccessors.values();
}
/**
* INTERNAL:
*/
public Collection<XMLEntityMappings> getEntityMappings() {
return m_entityMappings.values();
}
/**
* INTERNAL:
* Return the entity accessor for the given class.
*/
public InterfaceAccessor getInterfaceAccessor(String className) {
return m_interfaceAccessors.get(className);
}
/**
* INTERNAL:
* Return the logger used by the processor.
*/
public MetadataLogger getLogger() {
return m_logger;
}
/**
* INTERNAL:
*/
public MappedSuperclassAccessor getMappedSuperclassAccessor(MetadataClass cls) {
return getMappedSuperclassAccessor(cls.getName());
}
/**
* INTERNAL:
*/
public MappedSuperclassAccessor getMappedSuperclassAccessor(String className) {
return m_mappedSuperclasseAccessors.get(className);
}
/**
* INTERNAL:
*/
public Collection<MappedSuperclassAccessor> getMappedSuperclasses() {
return m_mappedSuperclasseAccessors.values();
}
/**
* INTERNAL:
* Returns the collection of metamodel MappedSuperclassAccessors. This
* collection is NOT and should NOT be used for any deployment descriptor
* metadata processing. It is used solely with the metamodel.
* @see #getMappedSuperclassAccessor(MetadataClass)
* @see #getMappedSuperclassAccessor(String)
* @see #getMappedSuperclasses()
* @since EclipseLink 1.2 for the JPA 2.0 Reference Implementation
*/
public Collection<MappedSuperclassAccessor> getMetamodelMappedSuperclasses() {
return m_metamodelMappedSuperclasses.values();
}
/**
* INTERNAL:
* Return the named partitioning policy.
*/
public AbstractPartitioningMetadata getPartitioningPolicy(String name) {
return m_partitioningPolicies.get(name);
}
/**
* INTERNAL:
* Return the persistence unit default catalog.
*/
protected String getPersistenceUnitDefaultCatalog() {
if (m_persistenceUnitMetadata != null) {
return m_persistenceUnitMetadata.getCatalog();
}
return null;
}
/**
* INTERNAL:
* Return the persistence unit default schema.
*/
protected String getPersistenceUnitDefaultSchema() {
if (m_persistenceUnitMetadata != null) {
return m_persistenceUnitMetadata.getSchema();
}
return null;
}
/**
* INTERNAL:
*/
public PersistenceUnitInfo getPersistenceUnitInfo() {
return m_persistenceUnitInfo;
}
/**
* INTERNAL:
*/
public XMLPersistenceUnitMetadata getPersistenceUnitMetadata() {
return m_persistenceUnitMetadata;
}
/**
* INTERNAL:
* Return the named PLSQL or Oracle complex metadata type.
*/
public ComplexTypeMetadata getComplexTypeMetadata(String name) {
return m_complexMetadataTypes.get(name);
}
/**
* INTERNAL:
* Return the core API Project associated with this MetadataProject.
* @return
* @since EclipseLink 1.2 for the JPA 2.0 Reference Implementation
*/
public Project getProject() {
return m_session.getProject();
}
/**
* INTERNAL:
* Add a root level embeddable accessor. Nested embeddables will be
* pre-processed from their roots down.
* @see processStage1()
*/
public Collection<EmbeddableAccessor> getRootEmbeddableAccessors() {
return m_rootEmbeddableAccessors.values();
}
/**
* INTERNAL:
*/
public AbstractSession getSession() {
return m_session;
}
/**
* INTERNAL:
* This method will return the name of the SharedCacheMode if specified in
* the persistence.xml file. Note, this is a JPA 2.0 feature, therefore,
* this method needs to catch any exception as a result of trying to access
* this information from a JPA 1.0 container.
*/
protected String getSharedCacheModeName() {
if (! m_isSharedCacheModeInitialized && m_sharedCacheMode == null) {
try {
Method method = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
method = AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(PersistenceUnitInfo.class, "getSharedCacheMode", null));
m_sharedCacheMode = (SharedCacheMode) AccessController.doPrivileged(new PrivilegedMethodInvoker(method, m_persistenceUnitInfo));
} else {
method = PrivilegedAccessHelper.getDeclaredMethod(PersistenceUnitInfo.class, "getSharedCacheMode", null);
m_sharedCacheMode = (SharedCacheMode) PrivilegedAccessHelper.invokeMethod(method, m_persistenceUnitInfo, null);
}
} catch (Throwable exception) {
// Swallow any exceptions, shared cache mode will be null.
m_sharedCacheMode = null;
}
// Set the shared cache mode as initialized to avoid the reflective
// calls over and over again.
m_isSharedCacheModeInitialized = true;
}
return (m_sharedCacheMode == null) ? null : m_sharedCacheMode.name();
}
/**
* INTERNAL:
* Sets the SharedCacheMode value.
*/
public void setSharedCacheMode(SharedCacheMode m_sharedCacheMode) {
this.m_sharedCacheMode = m_sharedCacheMode;
}
/**
* INTERNAL:
* Used to uppercase default and user defined column field names
*/
public boolean getShouldForceFieldNamesToUpperCase(){
return m_forceFieldNamesToUpperCase;
}
/**
* INTERNAL:
*/
public List<StructConverterMetadata> getStructConverters(){
List<StructConverterMetadata> structConverters = new ArrayList<StructConverterMetadata>();
for (AbstractConverterMetadata converter : m_converters.values()) {
if (converter.isStructConverter()) {
structConverters.add((StructConverterMetadata) converter);
}
}
return structConverters;
}
/**
* INTERNAL:
* Returns all those classes in this project that are available for
* weaving. This list currently includes entity, embeddables
* and mappedsuperclass with no children classes.
*/
public Collection<String> getWeavableClassNames() {
Set<String> weavableClassNames = new HashSet<String>(m_allAccessors.keySet());
weavableClassNames.addAll(m_mappedSuperclasseAccessors.keySet());
return Collections.unmodifiableCollection(weavableClassNames);
}
/**
* Return true if there is an auto-apply converter for the given cls.
*/
public boolean hasAutoApplyConverter(MetadataClass cls) {
boolean hasCA = m_autoApplyConvertAccessors.containsKey(cls.getName());
if (hasCA == false) {
String wrapperType = resolvePrimitiveWrapper(cls);
if (wrapperType != null) {
hasCA = m_autoApplyConvertAccessors.containsKey(wrapperType);
}
}
return hasCA;
}
/**
* INTERNAL:
*/
public boolean hasConverter(String name) {
return m_converters.containsKey(name);
}
/**
* INTERNAL:
*/
public boolean hasConverterAccessor(MetadataClass cls) {
return m_converterAccessors.containsKey(cls.getName());
}
/**
* INTERNAL:
*/
public boolean hasEmbeddable(MetadataClass cls) {
return hasEmbeddable(cls.getName());
}
/**
* INTERNAL:
*/
public boolean hasEmbeddable(String className) {
return m_embeddableAccessors.containsKey(className);
}
/**
* INTERNAL:
*/
public boolean hasEntity(MetadataClass cls) {
return hasEntity(cls.getName());
}
/**
* INTERNAL:
*/
public boolean hasEntity(String className) {
return m_entityAccessors.containsKey(className);
}
/**
* INTERNAL:
* Return true is there exist and entity graph already for the given name.
*/
public boolean hasEntityGraph(String name) {
return getProject().getAttributeGroups().containsKey(name);
}
/**
* INTERNAL:
*/
public boolean hasEntityThatImplementsInterface(String interfaceName) {
return m_interfacesImplementedByEntities.contains(interfaceName);
}
/**
* INTERNAL:
*/
public boolean hasInterface(MetadataClass cls) {
return m_interfaceAccessors.containsKey(cls.getName());
}
/**
* INTERNAL:
*/
public boolean hasMappedSuperclass(MetadataClass cls) {
return hasMappedSuperclass(cls.getName());
}
/**
* INTERNAL:
*/
public boolean hasMappedSuperclass(String className) {
return m_mappedSuperclasseAccessors.containsKey(className);
}
/**
* INTERNAL:
*/
public boolean hasSharedCacheMode() {
return getSharedCacheModeName() != null;
}
/**
* INTERNAL:
*/
public boolean isIdClass(MetadataClass idClass) {
return m_idClasses.contains(idClass.getName());
}
/**
* INTERNAL:
* Return true if the caching has been specified as ALL in the
* persistence.xml.
*/
public boolean isSharedCacheModeAll() {
return hasSharedCacheMode() && getSharedCacheModeName().equals(SharedCacheMode.ALL.name());
}
/**
* INTERNAL:
* Return true if the caching has been specified as DISABLE_SELECTIVE in the
* persistence.xml. DISABLE_SELECTIVE is the default therefore this will
* also return true if no caching setting was set.
*/
public boolean isSharedCacheModeDisableSelective() {
return (! hasSharedCacheMode()) || getSharedCacheModeName().equals(SharedCacheMode.DISABLE_SELECTIVE.name());
}
/**
* INTERNAL:
* Return true if the caching has been specified as ENABLE_SELECTIVE in the
* persistence.xml.
*/
public boolean isSharedCacheModeEnableSelective() {
return hasSharedCacheMode() && getSharedCacheModeName().equals(SharedCacheMode.ENABLE_SELECTIVE.name());
}
/**
* INTERNAL:
* Return true if the caching has been specified as NONE in the
* persistence.xml.
*/
public boolean isSharedCacheModeNone() {
return hasSharedCacheMode() && getSharedCacheModeName().equals(SharedCacheMode.NONE.name());
}
/**
* INTERNAL:
* Return true if the caching has been specified as UNSPECIFIED in the
* persistence.xml.
*/
public boolean isSharedCacheModeUnspecified() {
return hasSharedCacheMode() && getSharedCacheModeName().equals(SharedCacheMode.UNSPECIFIED.name());
}
/**
* INTERNAL:
* Return if the project should use indirection for eager relationships.
*/
public boolean isWeavingEagerEnabled() {
return m_isWeavingEagerEnabled;
}
/**
* INTERNAL:
* Return if the project should process fetch groups.
*/
public boolean isWeavingFetchGroupsEnabled() {
return m_isWeavingFetchGroupsEnabled;
}
/**
* INTERNAL:
* Return if the project should use indirection for lazy relationships.
*/
public boolean isWeavingLazyEnabled() {
return m_isWeavingLazyEnabled;
}
/**
* INTERNAL:
* Return true if an xml-mapping-metadata-complete setting has been set
* for this persistence unit.
*/
public boolean isXMLMappingMetadataComplete() {
if (m_persistenceUnitMetadata != null) {
return m_persistenceUnitMetadata.isXMLMappingMetadataComplete();
}
return false;
}
/**
* INTERNAL:
* Process the embeddable mapping accessors.
*/
protected void processEmbeddableMappingAccessors() {
for (MappingAccessor mappingAccessor : m_embeddableMappingAccessors) {
if (! mappingAccessor.isProcessed()) {
mappingAccessor.process();
}
}
}
/**
* INTERNAL:
* Process descriptors with IDs derived from relationships. This will also
* complete unfinished validation as well as secondary table processing
* on entity accessors. This method will fast track some relationship
* mappings which is ok since simple primary keys will already have been
* discovered and processed whereas any derived id's and their fast tracking
* to be processed will be handled now.
*/
protected void processAccessorsWithDerivedIDs() {
HashSet<ClassAccessor> processed = new HashSet();
HashSet<ClassAccessor> processing = new HashSet();
for (ClassAccessor classAccessor : m_accessorsWithDerivedId.values()) {
classAccessor.processDerivedId(processing, processed);
}
}
/**
* INTERNAL:
* Process any BasicCollection annotation and/or BasicMap annotation that
* were found. They are not processed till after an id has been processed
* since they rely on one to map the collection table.
*/
public void processDirectCollectionAccessors() {
for (DirectCollectionAccessor accessor : m_directCollectionAccessors) {
accessor.process();
}
}
/**
* INTERNAL:
* This method will iterate through all the entities in the PU and check
* if we should add them to a variable one to one mapping that was either
* defined (incompletely) or defaulted.
*/
protected void processInterfaceAccessors() {
for (EntityAccessor accessor : getEntityAccessors()) {
for (String interfaceClass : accessor.getJavaClass().getInterfaces()) {
if (m_interfaceAccessors.containsKey(interfaceClass)) {
m_interfaceAccessors.get(interfaceClass).addEntityAccessor(accessor);
}
}
}
}
/**
* INTERNAL:
* Process the non-owning relationship accessors. All owning relationshuip
* accessors should be processed. Some non-owning relationships may have
* already been fast tracked to from an element collection containing
* an embeddable (with a non-owning relationship).
*/
protected void processNonOwningRelationshipAccessors() {
for (RelationshipAccessor accessor : m_nonOwningRelationshipAccessors) {
if (! accessor.isProcessed()) {
accessor.process();
}
}
}
/**
* INTERNAL:
* Process the owning relationship accessors. Some may have already been
* processed through the processing of derived id's therefore don't process
* them again.
*/
protected void processOwningRelationshipAccessors() {
for (RelationshipAccessor accessor : m_owningRelationshipAccessors) {
if (! accessor.isProcessed()) {
accessor.process();
}
}
}
/**
* INTERNAL:
* Process any and all persistence unit metadata and defaults to the given
* descriptor. This method for will called for every descriptor belonging
* to this project/persistence unit.
*
*/
protected void processPersistenceUnitMetadata(MetadataDescriptor descriptor) {
// Set the persistence unit meta data (if there is any) on the descriptor.
if (m_persistenceUnitMetadata != null) {
// Persistence unit metadata level annotations are not defaults
// and therefore should not be set on the descriptor.
// Set the persistence unit defaults (if there are any) on the descriptor.
XMLPersistenceUnitDefaults persistenceUnitDefaults = m_persistenceUnitMetadata.getPersistenceUnitDefaults();
if (persistenceUnitDefaults != null) {
descriptor.setDefaultAccess(persistenceUnitDefaults.getAccess());
descriptor.setDefaultSchema(persistenceUnitDefaults.getSchema());
descriptor.setDefaultCatalog(persistenceUnitDefaults.getCatalog());
descriptor.setDefaultTenantDiscriminatorColumns(persistenceUnitDefaults.getTenantDiscriminatorColumns());
descriptor.setIsCascadePersist(persistenceUnitDefaults.isCascadePersist());
// Set any default access methods if specified.
if (persistenceUnitDefaults.hasAccessMethods()) {
descriptor.setDefaultAccessMethods(persistenceUnitDefaults.getAccessMethods());
}
}
}
}
/**
* INTERNAL:
* Process the named native queries we found and add them to the given
* session.
*/
public void processQueries() {
// Step 1 - process the sql result set mappings first.
for (SQLResultSetMappingMetadata sqlResultSetMapping : m_sqlResultSetMappings.values()) {
m_session.getProject().addSQLResultSetMapping(sqlResultSetMapping.process());
}
// Step 2 - process the named queries second, some may need to validate
// a sql result set mapping specification.
for (NamedQueryMetadata query : m_queries.values()) {
query.process(m_session);
}
}
/**
* INTERNAL:
* Process the sequencing information. At this point, through validation, it
* is not possible to have:
* 1 - a table generator with the generator name equal to
* DEFAULT_SEQUENCE_GENERATOR or DEFAULT_IDENTITY_GENERATOR
* 2 - a sequence generator with the name eqaul to DEFAULT_TABLE_GENERATOR
* or DEFAULT_IDENTITY_GENERATOR
* 3 - you can't have both a sequence generator and a table generator with
* the same DEFAULT_AUTO_GENERATOR name.
*
* @see addTableGenerator and addSequenceGenerator.
*/
protected void processSequencingAccessors() {
if (! m_generatedValues.isEmpty()) {
// 1 - Build our map of sequences keyed on generator names.
Hashtable<String, Sequence> sequences = new Hashtable<String, Sequence>();
for (SequenceGeneratorMetadata sequenceGenerator : m_sequenceGenerators.values()) {
sequences.put(sequenceGenerator.getName(), sequenceGenerator.process(m_logger));
}
for (UuidGeneratorMetadata uuidGenerator : m_uuidGenerators.values()) {
sequences.put(uuidGenerator.getName(), uuidGenerator.process(m_logger));
}
for (TableGeneratorMetadata tableGenerator : m_tableGenerators.values()) {
sequences.put(tableGenerator.getGeneratorName(), tableGenerator.process(m_logger));
}
// 2 - Check if the user defined default generators, otherwise
// create them using the Table and Sequence generator metadata.
if (! sequences.containsKey(DEFAULT_TABLE_GENERATOR)) {
TableGeneratorMetadata tableGenerator = new TableGeneratorMetadata(DEFAULT_TABLE_GENERATOR);
// This code was attempting to use the platform default sequence name,
// however the platform has not been set yet, so it would never work,
// it was also causing the platform default sequence to be set, causing the DatabasePlatform default to be used,
// so I am removing this code, as it breaks the platform default sequence and does not work.
// Sequence seq = m_session.getDatasourcePlatform().getDefaultSequence();
// Using "" as the default should make the platform default it.
String defaultTableGeneratorName = "";
// Process the default values.
processTable(tableGenerator, defaultTableGeneratorName, getPersistenceUnitDefaultCatalog(), getPersistenceUnitDefaultSchema(), tableGenerator);
sequences.put(DEFAULT_TABLE_GENERATOR, tableGenerator.process(m_logger));
}
if (! sequences.containsKey(DEFAULT_SEQUENCE_GENERATOR)) {
sequences.put(DEFAULT_SEQUENCE_GENERATOR, new SequenceGeneratorMetadata(DEFAULT_SEQUENCE_GENERATOR, getPersistenceUnitDefaultCatalog(), getPersistenceUnitDefaultSchema()).process(m_logger));
}
if (! sequences.containsKey(DEFAULT_IDENTITY_GENERATOR)) {
sequences.put(DEFAULT_IDENTITY_GENERATOR, new SequenceGeneratorMetadata(DEFAULT_IDENTITY_GENERATOR, 1, getPersistenceUnitDefaultCatalog(), getPersistenceUnitDefaultSchema(), true).process(m_logger));
}
// Use a temporary sequence generator to build a qualifier to set on
// the default generator. Don't use this generator as the default
// auto generator though.
SequenceGeneratorMetadata tempGenerator = new SequenceGeneratorMetadata(DEFAULT_AUTO_GENERATOR, getPersistenceUnitDefaultCatalog(), getPersistenceUnitDefaultSchema());
DatasourceLogin login = m_session.getProject().getLogin();
login.setTableQualifier(tempGenerator.processQualifier());
// 3 - Loop through generated values and set sequences for each.
for (MetadataClass entityClass : m_generatedValues.keySet()) {
// Skip setting sequences if our accessor is null, must be a mapped superclass
ClassAccessor accessor = m_allAccessors.get(entityClass.getName());
if (accessor != null) {
m_generatedValues.get(entityClass).process(accessor.getDescriptor(), sequences, login);
}
}
}
}
/**
* Process the partitioning metedata and add the PartitioningPolicys to the project.
*/
protected void processPartitioning() {
for (AbstractPartitioningMetadata metadata : m_partitioningPolicies.values()) {
m_session.getProject().addPartitioningPolicy(metadata.buildPolicy());
}
}
/**
* INTERNAL:
* Stage 1 processing is a pre-processing stage that will perform the
* following tasks:
* - gather a list of mapping accessors for all entities and embeddables.
* - discover all global converter specifications.
* - discover mapped superclasses and inheritance parents.
*
* NOTE: This method should only perform any preparatory work like, class
* discovery, flag settings etc. Hard processing will begin in stage 2.
*
* @see processStage2
*/
public void processStage1() {
// 1 - Pre-process the entities first. This will also pre-process
// the mapped superclasses and build/add/complete our list of
// embeddables that will be pre-processed in step 2 below. This is
// necessary so that we may gather our list of id classes which may be
// referenced in embeddable classes as part of a mapped by id accessor.
// This will avoid more complicated processing and ease in building the
// correct accessor at buildAccessor time.
for (EntityAccessor entity : getEntityAccessors()) {
if (! entity.isPreProcessed()) {
entity.preProcess();
}
}
// 2 - Pre-process the embeddables. This will also pre-process any and
// all nested embeddables as well. Embeddables must be processed from
// the root down.
for (EmbeddableAccessor embeddable : getRootEmbeddableAccessors()) {
if (! embeddable.isPreProcessed()) {
embeddable.preProcess();
}
}
// 3 - Build our global converter and auto-apply lists first
for (ConverterAccessor converterAccessor : getConverterAccessors().values()) {
if (converterAccessor.autoApply()) {
m_autoApplyConvertAccessors.put(converterAccessor.getAttributeClassification().getName(), converterAccessor);
}
}
// 4 - Pre-process the embeddables.
for (EmbeddableAccessor embeddable : getEmbeddableAccessors()) {
// If the accessor hasn't been processed yet, then process it. An
// EmbeddableAccessor is normally fast tracked if it is a reference.
if (! embeddable.isPreProcessed()) {
embeddable.preProcess();
}
}
}
/**
* INTERNAL:
* Stage 2 processing will perform the following tasks:
* - process all direct mapping accessors from entities, embeddables and
* mapped superclasses.
* - gather a list of relationship accessors and any other special interest
* accessors to be processed in stage 3.
*
* @see processStage3
*/
public void processStage2() {
// process metamodel mappedSuperclasses separately from entity descriptors
for (MappedSuperclassAccessor msAccessor : getMetamodelMappedSuperclasses()) {
if (! msAccessor.isProcessed()) {
msAccessor.processMetamodelDescriptor();
}
}
for (EntityAccessor entity : getEntityAccessors()) {
// If the accessor hasn't been processed yet, then process it. An
// EntityAccessor may get fast tracked if it is an inheritance
// parent.
if (! entity.isProcessed()) {
entity.process();
}
}
for (EmbeddableAccessor embeddable : getEmbeddableAccessors()) {
// If the accessor hasn't been processed yet, then process it. An
// EmbeddableAccessor is normally fast tracked if it is a reference.
if (! embeddable.isProcessed()) {
embeddable.process();
}
}
}
/**
* INTERNAL:
* Stage 3 processing does all the extra processing that couldn't be
* completed in the first two stages of processing. The biggest thing
* being that all entities will have processed an id by now and we can
* process those accessors that rely on them. NOTE: The order of invocation
* here is very important here, see the comments.
*/
public void processStage3(PersistenceUnitProcessor.Mode mode) {
if (mode == PersistenceUnitProcessor.Mode.ALL || mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_MIDDLE) {
// 1 - Process accessors with IDs derived from relationships. This will
// finish up any stage2 processing that relied on the PK processing
// being complete as well. Note: some relationships mappings may be
// processed in this stage. This is ok since it is to determine and
// validate the primary key.
processAccessorsWithDerivedIDs();
// 2 - Process all the direct collection accessors we found. This list
// does not include direct collections to an embeddable class.
processDirectCollectionAccessors();
// 3 - Process the sequencing metadata now that every entity has a
// validated primary key.
processSequencingAccessors();
// 4 - Process the owning relationship accessors now that every entity
// has a validated primary key and we can process join columns.
processOwningRelationshipAccessors();
// 5 - Process the embeddable mapping accessors. These are the
// embedded, embedded id and element collection accessors that map
// to an embeddable class. We must hold off on their processing till
// now to ensure their owning relationship accessors have been processed
// and we can therefore process any association overrides correctly.
processEmbeddableMappingAccessors();
// composite persistence unit case
if (getCompositeProcessor() != null) {
for (EmbeddableAccessor accessor : getEmbeddableAccessors()) {
if (! accessor.isProcessed()) {
accessor.process();
}
}
}
}
if (mode == PersistenceUnitProcessor.Mode.ALL || mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_FINAL) {
// 6 - Process the non owning relationship accessors now that every
// owning relationship should be fully processed.
processNonOwningRelationshipAccessors();
// 7 - Process the interface accessors which will iterate through all
// the entities in the PU and check if we should add them to a variable
// one to one mapping that was either defined (incompletely) or
// defaulted.
processInterfaceAccessors();
processPartitioning();
}
}
/**
* INTERNAL:
* Common table processing for table, secondary table, join table,
* collection table and table generators
*/
public void processTable(TableMetadata table, String defaultName, String defaultCatalog, String defaultSchema, ORMetadata owner) {
// Name could be "" or null, need to check against the default name.
String name = MetadataHelper.getName(table.getName(), defaultName, table.getNameContext(), m_logger, owner.getAccessibleObject());
// Catalog could be "" or null, need to check for an XML default.
String catalog = MetadataHelper.getName(table.getCatalog(), defaultCatalog, table.getCatalogContext(), m_logger, owner.getAccessibleObject());
// Schema could be "" or null, need to check for an XML default.
String schema = MetadataHelper.getName(table.getSchema(), defaultSchema, table.getSchemaContext(), m_logger, owner.getAccessibleObject());
// Build a fully qualified name and set it on the table.
// schema, attach it if specified
String tableName = name;
if (! schema.equals("")) {
tableName = schema + "." + tableName;
}
// catalog, attach it if specified
if (! catalog.equals("")) {
tableName = catalog + "." + tableName;
}
table.setFullyQualifiedTableName(tableName);
if (useDelimitedIdentifier()) {
table.setUseDelimiters(useDelimitedIdentifier());
}
// Process the unique constraints.
table.processUniqueConstraints();
// Process the index metadata.
table.processIndexes();
// Process the foreign key metadata.
table.processForeignKey();
// Process the creation suffix.
table.processCreationSuffix();
}
/**
* INTERNAL:
* Used from the canonical model generator. Specifically when the user
* removes the embeddable designation or changes the embeddable to either
* a mapped superclass or entity.
*/
public void removeEmbeddableAccessor(MetadataClass metadataClass) {
m_allAccessors.remove(metadataClass.getName());
m_embeddableAccessors.remove(metadataClass.getName());
}
/**
* INTERNAL:
* Used from the canonical model generator. Specifically when the user
* removes the entity designation or changes the entity to either
* a mapped superclass or embeddable.
*/
public void removeEntityAccessor(MetadataClass metadataClass) {
m_allAccessors.remove(metadataClass.getName());
m_entityAccessors.remove(metadataClass.getName());
}
/**
* INTERNAL:
* Used from the canonical model generator. Specifically when the user
* removes the mapped superclass designation or changes the mapped
* superclass to either an entity or embeddable.
*/
public void removeMappedSuperclassAccessor(MetadataClass metadataClass) {
m_mappedSuperclasseAccessors.remove(metadataClass.getName());
}
/**
* INTERNAL:
* When at least one entity is found that is multitenant, we turn off
* native SQL queries.
*/
public void setAllowNativeSQLQueries(boolean allowNativeSQLQueries) {
getProject().setAllowNativeSQLQueries(allowNativeSQLQueries);
}
/**
* INTERNAL:
* set compositeProcessor that owns this and pear MetadataProcessors used to create composite persistence unit.
*/
public void setCompositeProcessor(MetadataProcessor compositeProcessor) {
m_compositeProcessor = compositeProcessor;
}
/**
* INTERNAL:
*/
public void setPersistenceUnitMetadata(XMLPersistenceUnitMetadata persistenceUnitMetadata) {
// Set the persistence unit metadata if null otherwise try to merge.
if (m_persistenceUnitMetadata == null) {
m_persistenceUnitMetadata = persistenceUnitMetadata;
} else {
m_persistenceUnitMetadata.merge(persistenceUnitMetadata);
}
}
/**
* INTERNAL:
* Used to uppercase default and user defined column field names
*/
public void setShouldForceFieldNamesToUpperCase(boolean shouldForceFieldNamesToUpperCase){
m_forceFieldNamesToUpperCase = shouldForceFieldNamesToUpperCase;
}
/**
* INTERNAL:
*/
@Override
public String toString() {
return "Project[" + getPersistenceUnitInfo().getPersistenceUnitName() + "]";
}
/**
* INTERNAL:
*/
public boolean useDelimitedIdentifier() {
return m_persistenceUnitMetadata != null && m_persistenceUnitMetadata.isDelimitedIdentifiers();
}
/**
* INTERNAL:
* Return true if the entity manager factory cache for this project is
* intended to be shared amongst multitenants.
*/
public boolean usesMultitenantSharedCache() {
return m_multitenantSharedCache;
}
/**
* INTERNAL:
* Return true if the entity manager factory for this project is intended
* to be shared amongst multitenants.
*/
public boolean usesMultitenantSharedEmf() {
return m_multitenantSharedEmf;
}
/**
* INTERNAL:
* Return true if the entity manager factory for this project has any virtual classes
*
*/
public boolean hasVirtualClasses() {
if ((m_virtualClasses != null) && (!m_virtualClasses.isEmpty())) {
return true;
}
return false;
}
}
|